1 | /* $Id$ */ |
---|
2 | |
---|
3 | /* |
---|
4 | * Copyright (c) 1995 Gordon Ross, Adam Glass |
---|
5 | * Copyright (c) 1992 Regents of the University of California. |
---|
6 | * All rights reserved. |
---|
7 | * |
---|
8 | * This software was developed by the Computer Systems Engineering group |
---|
9 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and |
---|
10 | * contributed to Berkeley. |
---|
11 | * |
---|
12 | * Redistribution and use in source and binary forms, with or without |
---|
13 | * modification, are permitted provided that the following conditions |
---|
14 | * are met: |
---|
15 | * 1. Redistributions of source code must retain the above copyright |
---|
16 | * notice, this list of conditions and the following disclaimer. |
---|
17 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
18 | * notice, this list of conditions and the following disclaimer in the |
---|
19 | * documentation and/or other materials provided with the distribution. |
---|
20 | * 3. All advertising materials mentioning features or use of this software |
---|
21 | * must display the following acknowledgement: |
---|
22 | * This product includes software developed by the University of |
---|
23 | * California, Lawrence Berkeley Laboratory and its contributors. |
---|
24 | * 4. Neither the name of the University nor the names of its contributors |
---|
25 | * may be used to endorse or promote products derived from this software |
---|
26 | * without specific prior written permission. |
---|
27 | * |
---|
28 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
---|
29 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
---|
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
---|
31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
---|
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
---|
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
---|
34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
---|
36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
---|
37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
---|
38 | * SUCH DAMAGE. |
---|
39 | * |
---|
40 | * based on: |
---|
41 | * nfs/krpc_subr.c |
---|
42 | * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $ |
---|
43 | */ |
---|
44 | |
---|
45 | #include <sys/param.h> |
---|
46 | #include <sys/systm.h> |
---|
47 | #include <sys/kernel.h> |
---|
48 | #include <sys/conf.h> |
---|
49 | #include <sys/sockio.h> |
---|
50 | #include <sys/proc.h> |
---|
51 | #include <sys/mount.h> |
---|
52 | #include <sys/mbuf.h> |
---|
53 | #include <sys/reboot.h> |
---|
54 | #include <sys/socket.h> |
---|
55 | #include <sys/socketvar.h> |
---|
56 | |
---|
57 | #include <net/if.h> |
---|
58 | #include <net/route.h> |
---|
59 | |
---|
60 | #include <netinet/in.h> |
---|
61 | #include <net/if_types.h> |
---|
62 | #include <net/if_dl.h> |
---|
63 | #include <netinet/if_ether.h> |
---|
64 | |
---|
65 | #include <nfs/rpcv2.h> |
---|
66 | #include <nfs/nfsproto.h> |
---|
67 | #include <nfs/nfs.h> |
---|
68 | #include <nfs/nfsdiskless.h> |
---|
69 | #include <nfs/krpc.h> |
---|
70 | #include <nfs/xdr_subs.h> |
---|
71 | |
---|
72 | #include <sys/stat.h> |
---|
73 | #include <sys/types.h> |
---|
74 | #include <fcntl.h> |
---|
75 | #include <rtems/mkrootfs.h> |
---|
76 | #include <rtems/rtems_bsdnet.h> |
---|
77 | |
---|
78 | #define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */ |
---|
79 | |
---|
80 | /* |
---|
81 | * What is the longest we will wait before re-sending a request? |
---|
82 | * Note this is also the frequency of "RPC timeout" messages. |
---|
83 | * The re-send loop count sup linearly to this maximum, so the |
---|
84 | * first complaint will happen after (1+2+3+4+5)=15 seconds. |
---|
85 | */ |
---|
86 | #define MAX_RESEND_DELAY 5 /* seconds */ |
---|
87 | |
---|
88 | /* Definitions from RFC951 */ |
---|
89 | struct bootp_packet { |
---|
90 | u_int8_t op; |
---|
91 | u_int8_t htype; |
---|
92 | u_int8_t hlen; |
---|
93 | u_int8_t hops; |
---|
94 | u_int32_t xid; |
---|
95 | u_int16_t secs; |
---|
96 | u_int16_t flags; |
---|
97 | struct in_addr ciaddr; |
---|
98 | struct in_addr yiaddr; |
---|
99 | struct in_addr siaddr; |
---|
100 | struct in_addr giaddr; |
---|
101 | unsigned char chaddr[16]; |
---|
102 | char sname[64]; |
---|
103 | char file[128]; |
---|
104 | unsigned char vend[256]; |
---|
105 | }; |
---|
106 | |
---|
107 | #define IPPORT_BOOTPC 68 |
---|
108 | #define IPPORT_BOOTPS 67 |
---|
109 | |
---|
110 | extern int nfs_diskless_valid; |
---|
111 | extern struct nfsv3_diskless nfsv3_diskless; |
---|
112 | |
---|
113 | /* mountd RPC */ |
---|
114 | #if !defined(__rtems__) |
---|
115 | static int md_mount __P((struct sockaddr_in *mdsin, char *path, |
---|
116 | u_char *fhp, int *fhsizep, struct nfs_args *args,struct proc *procp)); |
---|
117 | static int md_lookup_swap __P((struct sockaddr_in *mdsin,char *path, |
---|
118 | u_char *fhp, int *fhsizep, |
---|
119 | struct nfs_args *args, |
---|
120 | struct proc *procp)); |
---|
121 | static int setfs __P((struct sockaddr_in *addr, char *path, char *p)); |
---|
122 | static int getdec __P((char **ptr)); |
---|
123 | #endif |
---|
124 | #if !defined(__rtems__) |
---|
125 | static char *substr __P((char *a,char *b)); |
---|
126 | static void mountopts __P((struct nfs_args *args, char *p)); |
---|
127 | static int xdr_opaque_decode __P((struct mbuf **ptr,u_char *buf, |
---|
128 | int len)); |
---|
129 | static int xdr_int_decode __P((struct mbuf **ptr,int *iptr)); |
---|
130 | #endif |
---|
131 | static void printip __P((char *prefix,struct in_addr addr)); |
---|
132 | |
---|
133 | #ifdef BOOTP_DEBUG |
---|
134 | void bootpboot_p_sa(struct sockaddr *sa,struct sockaddr *ma); |
---|
135 | void bootpboot_p_ma(struct sockaddr *ma); |
---|
136 | void bootpboot_p_rtentry(struct rtentry *rt); |
---|
137 | void bootpboot_p_tree(struct radix_node *rn); |
---|
138 | void bootpboot_p_rtlist(void); |
---|
139 | void bootpboot_p_iflist(void); |
---|
140 | #endif |
---|
141 | |
---|
142 | int bootpc_call(struct bootp_packet *call, |
---|
143 | struct bootp_packet *reply, |
---|
144 | struct proc *procp); |
---|
145 | |
---|
146 | int bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, |
---|
147 | struct proc *procp); |
---|
148 | |
---|
149 | int |
---|
150 | bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, |
---|
151 | struct sockaddr_in *myaddr, |
---|
152 | struct sockaddr_in *netmask, |
---|
153 | struct sockaddr_in *gw, |
---|
154 | struct proc *procp); |
---|
155 | |
---|
156 | void bootpc_init(int update_files); |
---|
157 | |
---|
158 | #ifdef BOOTP_DEBUG |
---|
159 | void bootpboot_p_sa(sa,ma) |
---|
160 | struct sockaddr *sa; |
---|
161 | struct sockaddr *ma; |
---|
162 | { |
---|
163 | if (!sa) { |
---|
164 | printf("(sockaddr *) <null>"); |
---|
165 | return; |
---|
166 | } |
---|
167 | switch (sa->sa_family) { |
---|
168 | case AF_INET: |
---|
169 | { |
---|
170 | struct sockaddr_in *sin = (struct sockaddr_in *) sa; |
---|
171 | printf("inet %x",ntohl(sin->sin_addr.s_addr)); |
---|
172 | if (ma) { |
---|
173 | struct sockaddr_in *sin = (struct sockaddr_in *) ma; |
---|
174 | printf(" mask %x",ntohl(sin->sin_addr.s_addr)); |
---|
175 | } |
---|
176 | } |
---|
177 | break; |
---|
178 | case AF_LINK: |
---|
179 | { |
---|
180 | struct sockaddr_dl *sli = (struct sockaddr_dl *) sa; |
---|
181 | int i; |
---|
182 | printf("link %.*s ",sli->sdl_nlen,sli->sdl_data); |
---|
183 | for (i=0;i<sli->sdl_alen;i++) { |
---|
184 | if (i>0) |
---|
185 | printf(":"); |
---|
186 | printf("%x",(unsigned char) sli->sdl_data[i+sli->sdl_nlen]); |
---|
187 | } |
---|
188 | } |
---|
189 | break; |
---|
190 | default: |
---|
191 | printf("af%d",sa->sa_family); |
---|
192 | } |
---|
193 | } |
---|
194 | |
---|
195 | void bootpboot_p_ma(ma) |
---|
196 | struct sockaddr *ma; |
---|
197 | { |
---|
198 | if (!ma) { |
---|
199 | printf("<null>"); |
---|
200 | return; |
---|
201 | } |
---|
202 | printf("%x",*(int*)ma); |
---|
203 | } |
---|
204 | |
---|
205 | void bootpboot_p_rtentry(rt) |
---|
206 | struct rtentry *rt; |
---|
207 | { |
---|
208 | bootpboot_p_sa(rt_key(rt),rt_mask(rt)); |
---|
209 | printf(" "); |
---|
210 | bootpboot_p_ma(rt->rt_genmask); |
---|
211 | printf(" "); |
---|
212 | bootpboot_p_sa(rt->rt_gateway,NULL); |
---|
213 | printf(" "); |
---|
214 | printf("flags %x",(unsigned short) rt->rt_flags); |
---|
215 | printf(" %d",rt->rt_rmx.rmx_expire); |
---|
216 | printf(" %s%d\n",rt->rt_ifp->if_name,rt->rt_ifp->if_unit); |
---|
217 | } |
---|
218 | void bootpboot_p_tree(rn) |
---|
219 | struct radix_node *rn; |
---|
220 | { |
---|
221 | while (rn) { |
---|
222 | if (rn->rn_b < 0) { |
---|
223 | if (rn->rn_flags & RNF_ROOT) { |
---|
224 | } else { |
---|
225 | bootpboot_p_rtentry((struct rtentry *) rn); |
---|
226 | } |
---|
227 | rn = rn->rn_dupedkey; |
---|
228 | } else { |
---|
229 | bootpboot_p_tree(rn->rn_l); |
---|
230 | bootpboot_p_tree(rn->rn_r); |
---|
231 | return; |
---|
232 | } |
---|
233 | |
---|
234 | } |
---|
235 | } |
---|
236 | |
---|
237 | void bootpboot_p_rtlist(void) |
---|
238 | { |
---|
239 | printf("Routing table:\n"); |
---|
240 | bootpboot_p_tree(rt_tables[AF_INET]->rnh_treetop); |
---|
241 | } |
---|
242 | |
---|
243 | void bootpboot_p_iflist(void) |
---|
244 | { |
---|
245 | struct ifnet *ifp; |
---|
246 | struct ifaddr *ifa; |
---|
247 | printf("Interface list:\n"); |
---|
248 | for (ifp = TAILQ_FIRST(&ifnet); ifp != 0; ifp = TAILQ_NEXT(ifp,if_link)) |
---|
249 | { |
---|
250 | for (ifa = TAILQ_FIRST(&ifp->if_addrhead) ;ifa; |
---|
251 | ifa=TAILQ_NEXT(ifa,ifa_link)) |
---|
252 | if (ifa->ifa_addr->sa_family == AF_INET ) { |
---|
253 | printf("%s%d flags %x, addr %x, bcast %x, net %x\n", |
---|
254 | ifp->if_name,ifp->if_unit, |
---|
255 | (unsigned short) ifp->if_flags, |
---|
256 | ntohl(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr), |
---|
257 | ntohl(((struct sockaddr_in *) ifa->ifa_dstaddr)->sin_addr.s_addr), |
---|
258 | ntohl(((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr) |
---|
259 | ); |
---|
260 | } |
---|
261 | } |
---|
262 | } |
---|
263 | #endif |
---|
264 | |
---|
265 | /* |
---|
266 | * - determine space needed to store src string |
---|
267 | * - allocate or reallocate dst, so that string fits in |
---|
268 | * - copy string from src to dest |
---|
269 | */ |
---|
270 | void *bootp_strdup_realloc(char *dst,const char *src) |
---|
271 | { |
---|
272 | size_t len; |
---|
273 | void *realloc(void * __r, size_t __size); |
---|
274 | |
---|
275 | if (dst == NULL) { |
---|
276 | /* first allocation, simply use strdup */ |
---|
277 | dst = strdup(src); |
---|
278 | } |
---|
279 | else { |
---|
280 | /* already allocated, so use realloc/strcpy */ |
---|
281 | len = strlen(src) + 1; |
---|
282 | dst = realloc(dst,len); |
---|
283 | if (dst != NULL) { |
---|
284 | strcpy(dst,src); |
---|
285 | } |
---|
286 | } |
---|
287 | return dst; |
---|
288 | } |
---|
289 | |
---|
290 | int |
---|
291 | bootpc_call(call,reply,procp) |
---|
292 | struct bootp_packet *call; |
---|
293 | struct bootp_packet *reply; /* output */ |
---|
294 | struct proc *procp; |
---|
295 | { |
---|
296 | struct socket *so; |
---|
297 | struct sockaddr_in *sin; |
---|
298 | struct mbuf *m, *nam; |
---|
299 | struct uio auio; |
---|
300 | struct iovec aio; |
---|
301 | int error, rcvflg, timo, secs, len; |
---|
302 | |
---|
303 | /* Free at end if not null. */ |
---|
304 | nam = NULL; |
---|
305 | |
---|
306 | /* |
---|
307 | * Create socket and set its recieve timeout. |
---|
308 | */ |
---|
309 | if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp))) |
---|
310 | goto out; |
---|
311 | |
---|
312 | m = m_get(M_WAIT, MT_SOOPTS); |
---|
313 | if (m == NULL) { |
---|
314 | error = ENOBUFS; |
---|
315 | goto out; |
---|
316 | } else { |
---|
317 | struct timeval *tv; |
---|
318 | tv = mtod(m, struct timeval *); |
---|
319 | m->m_len = sizeof(*tv); |
---|
320 | tv->tv_sec = 1; |
---|
321 | tv->tv_usec = 0; |
---|
322 | if ((error = sosetopt(so, SOL_SOCKET, SO_RCVTIMEO, m))) |
---|
323 | goto out; |
---|
324 | } |
---|
325 | |
---|
326 | /* |
---|
327 | * Enable broadcast. |
---|
328 | */ |
---|
329 | { |
---|
330 | int *on; |
---|
331 | m = m_get(M_WAIT, MT_SOOPTS); |
---|
332 | if (m == NULL) { |
---|
333 | error = ENOBUFS; |
---|
334 | goto out; |
---|
335 | } |
---|
336 | on = mtod(m, int *); |
---|
337 | m->m_len = sizeof(*on); |
---|
338 | *on = 1; |
---|
339 | if ((error = sosetopt(so, SOL_SOCKET, SO_BROADCAST, m))) |
---|
340 | goto out; |
---|
341 | } |
---|
342 | |
---|
343 | /* |
---|
344 | * Bind the local endpoint to a bootp client port. |
---|
345 | */ |
---|
346 | m = m_getclr(M_WAIT, MT_SONAME); |
---|
347 | sin = mtod(m, struct sockaddr_in *); |
---|
348 | sin->sin_len = m->m_len = sizeof(*sin); |
---|
349 | sin->sin_family = AF_INET; |
---|
350 | sin->sin_addr.s_addr = INADDR_ANY; |
---|
351 | sin->sin_port = htons(IPPORT_BOOTPC); |
---|
352 | error = sobind(so, m); |
---|
353 | m_freem(m); |
---|
354 | if (error) { |
---|
355 | printf("bind failed\n"); |
---|
356 | goto out; |
---|
357 | } |
---|
358 | |
---|
359 | /* |
---|
360 | * Setup socket address for the server. |
---|
361 | */ |
---|
362 | nam = m_get(M_WAIT, MT_SONAME); |
---|
363 | if (nam == NULL) { |
---|
364 | error = ENOBUFS; |
---|
365 | goto out; |
---|
366 | } |
---|
367 | sin = mtod(nam, struct sockaddr_in *); |
---|
368 | sin-> sin_len = sizeof(*sin); |
---|
369 | sin-> sin_family = AF_INET; |
---|
370 | sin->sin_addr.s_addr = INADDR_BROADCAST; |
---|
371 | sin->sin_port = htons(IPPORT_BOOTPS); |
---|
372 | |
---|
373 | nam->m_len = sizeof(*sin); |
---|
374 | |
---|
375 | /* |
---|
376 | * Send it, repeatedly, until a reply is received, |
---|
377 | * but delay each re-send by an increasing amount. |
---|
378 | * If the delay hits the maximum, start complaining. |
---|
379 | */ |
---|
380 | timo = 0; |
---|
381 | for (;;) { |
---|
382 | /* Send BOOTP request (or re-send). */ |
---|
383 | |
---|
384 | aio.iov_base = (caddr_t) call; |
---|
385 | aio.iov_len = sizeof(*call); |
---|
386 | |
---|
387 | auio.uio_iov = &aio; |
---|
388 | auio.uio_iovcnt = 1; |
---|
389 | auio.uio_segflg = UIO_SYSSPACE; |
---|
390 | auio.uio_rw = UIO_WRITE; |
---|
391 | auio.uio_offset = 0; |
---|
392 | auio.uio_resid = sizeof(*call); |
---|
393 | auio.uio_procp = procp; |
---|
394 | |
---|
395 | error = sosend(so, nam, &auio, NULL, NULL, 0); |
---|
396 | if (error) { |
---|
397 | printf("bootpc_call: sosend: %d\n", error); |
---|
398 | goto out; |
---|
399 | } |
---|
400 | |
---|
401 | /* Determine new timeout. */ |
---|
402 | if (timo < MAX_RESEND_DELAY) |
---|
403 | timo++; |
---|
404 | else |
---|
405 | printf("BOOTP timeout for server 0x%x\n", |
---|
406 | (int)ntohl(sin->sin_addr.s_addr)); |
---|
407 | |
---|
408 | /* |
---|
409 | * Wait for up to timo seconds for a reply. |
---|
410 | * The socket receive timeout was set to 1 second. |
---|
411 | */ |
---|
412 | secs = timo; |
---|
413 | while (secs > 0) { |
---|
414 | aio.iov_base = (caddr_t) reply; |
---|
415 | aio.iov_len = sizeof(*reply); |
---|
416 | |
---|
417 | auio.uio_iov = &aio; |
---|
418 | auio.uio_iovcnt = 1; |
---|
419 | auio.uio_segflg = UIO_SYSSPACE; |
---|
420 | auio.uio_rw = UIO_READ; |
---|
421 | auio.uio_offset = 0; |
---|
422 | auio.uio_resid = sizeof(*reply); |
---|
423 | auio.uio_procp = procp; |
---|
424 | |
---|
425 | rcvflg = 0; |
---|
426 | error = soreceive(so, NULL, &auio, NULL, NULL, &rcvflg); |
---|
427 | if (error == EWOULDBLOCK) { |
---|
428 | secs--; |
---|
429 | call->secs=htons(ntohs(call->secs)+1); |
---|
430 | continue; |
---|
431 | } |
---|
432 | if (error) |
---|
433 | goto out; |
---|
434 | len = sizeof(*reply) - auio.uio_resid; |
---|
435 | |
---|
436 | /* Do we have the required number of bytes ? */ |
---|
437 | if (len < BOOTP_MIN_LEN) |
---|
438 | continue; |
---|
439 | |
---|
440 | /* Is it the right reply? */ |
---|
441 | if (reply->op != 2) |
---|
442 | continue; |
---|
443 | |
---|
444 | if (reply->xid != call->xid) |
---|
445 | continue; |
---|
446 | |
---|
447 | if (reply->hlen != call->hlen) |
---|
448 | continue; |
---|
449 | |
---|
450 | if (bcmp(reply->chaddr,call->chaddr,call->hlen)) |
---|
451 | continue; |
---|
452 | |
---|
453 | goto gotreply; /* break two levels */ |
---|
454 | |
---|
455 | } /* while secs */ |
---|
456 | } /* forever send/receive */ |
---|
457 | |
---|
458 | error = ETIMEDOUT; |
---|
459 | goto out; |
---|
460 | |
---|
461 | gotreply: |
---|
462 | out: |
---|
463 | if (nam) m_freem(nam); |
---|
464 | soclose(so); |
---|
465 | return error; |
---|
466 | } |
---|
467 | |
---|
468 | int |
---|
469 | bootpc_fakeup_interface(struct ifreq *ireq,struct socket *so, |
---|
470 | struct proc *procp) |
---|
471 | { |
---|
472 | struct sockaddr_in *sin; |
---|
473 | int error; |
---|
474 | struct sockaddr_in dst; |
---|
475 | struct sockaddr_in gw; |
---|
476 | struct sockaddr_in mask; |
---|
477 | |
---|
478 | /* |
---|
479 | * Bring up the interface. |
---|
480 | * |
---|
481 | * Get the old interface flags and or IFF_UP into them; if |
---|
482 | * IFF_UP set blindly, interface selection can be clobbered. |
---|
483 | */ |
---|
484 | error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)ireq, procp); |
---|
485 | if (error) |
---|
486 | panic("bootpc_fakeup_interface: GIFFLAGS, error=%d", error); |
---|
487 | ireq->ifr_flags |= IFF_UP; |
---|
488 | error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)ireq, procp); |
---|
489 | if (error) |
---|
490 | panic("bootpc_fakeup_interface: SIFFLAGS, error=%d", error); |
---|
491 | |
---|
492 | /* |
---|
493 | * Do enough of ifconfig(8) so that the chosen interface |
---|
494 | * can talk to the servers. (just set the address) |
---|
495 | */ |
---|
496 | |
---|
497 | /* addr is 0.0.0.0 */ |
---|
498 | |
---|
499 | sin = (struct sockaddr_in *)&ireq->ifr_addr; |
---|
500 | bzero((caddr_t)sin, sizeof(*sin)); |
---|
501 | sin->sin_len = sizeof(*sin); |
---|
502 | sin->sin_family = AF_INET; |
---|
503 | sin->sin_addr.s_addr = INADDR_ANY; |
---|
504 | error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); |
---|
505 | if (error) |
---|
506 | panic("bootpc_fakeup_interface: set if addr, error=%d", error); |
---|
507 | |
---|
508 | /* netmask is 0.0.0.0 */ |
---|
509 | |
---|
510 | sin = (struct sockaddr_in *)&ireq->ifr_addr; |
---|
511 | bzero((caddr_t)sin, sizeof(*sin)); |
---|
512 | sin->sin_len = sizeof(*sin); |
---|
513 | sin->sin_family = AF_INET; |
---|
514 | sin->sin_addr.s_addr = INADDR_ANY; |
---|
515 | error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); |
---|
516 | if (error) |
---|
517 | panic("bootpc_fakeup_interface: set if net addr, error=%d", error); |
---|
518 | |
---|
519 | /* Broadcast is 255.255.255.255 */ |
---|
520 | |
---|
521 | sin = (struct sockaddr_in *)&ireq->ifr_addr; |
---|
522 | bzero((caddr_t)sin, sizeof(*sin)); |
---|
523 | sin->sin_len = sizeof(*sin); |
---|
524 | sin->sin_family = AF_INET; |
---|
525 | sin->sin_addr.s_addr = INADDR_BROADCAST; |
---|
526 | error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); |
---|
527 | if (error) |
---|
528 | panic("bootpc_fakeup_interface: set if broadcast addr, error=%d", error); |
---|
529 | |
---|
530 | /* Add default route to 0.0.0.0 so we can send data */ |
---|
531 | |
---|
532 | bzero((caddr_t) &dst, sizeof(dst)); |
---|
533 | dst.sin_len=sizeof(dst); |
---|
534 | dst.sin_family=AF_INET; |
---|
535 | dst.sin_addr.s_addr = htonl(0); |
---|
536 | |
---|
537 | bzero((caddr_t) &gw, sizeof(gw)); |
---|
538 | gw.sin_len=sizeof(gw); |
---|
539 | gw.sin_family=AF_INET; |
---|
540 | gw.sin_addr.s_addr = htonl(0x0); |
---|
541 | |
---|
542 | bzero((caddr_t) &mask, sizeof(mask)); |
---|
543 | mask.sin_len=sizeof(mask); |
---|
544 | mask.sin_family=AF_INET; |
---|
545 | mask.sin_addr.s_addr = htonl(0); |
---|
546 | |
---|
547 | error = rtrequest(RTM_ADD, |
---|
548 | (struct sockaddr *) &dst, |
---|
549 | (struct sockaddr *) &gw, |
---|
550 | (struct sockaddr *) &mask, |
---|
551 | RTF_UP | RTF_STATIC |
---|
552 | , NULL); |
---|
553 | if (error) |
---|
554 | printf("bootpc_fakeup_interface: add default route, error=%d\n", error); |
---|
555 | return error; |
---|
556 | } |
---|
557 | |
---|
558 | int |
---|
559 | bootpc_adjust_interface(struct ifreq *ireq,struct socket *so, |
---|
560 | struct sockaddr_in *myaddr, |
---|
561 | struct sockaddr_in *netmask, |
---|
562 | struct sockaddr_in *gw, |
---|
563 | struct proc *procp) |
---|
564 | { |
---|
565 | int error; |
---|
566 | struct sockaddr_in oldgw; |
---|
567 | struct sockaddr_in olddst; |
---|
568 | struct sockaddr_in oldmask; |
---|
569 | struct sockaddr_in *sin; |
---|
570 | |
---|
571 | /* Remove old default route to 0.0.0.0 */ |
---|
572 | |
---|
573 | bzero((caddr_t) &olddst, sizeof(olddst)); |
---|
574 | olddst.sin_len=sizeof(olddst); |
---|
575 | olddst.sin_family=AF_INET; |
---|
576 | olddst.sin_addr.s_addr = INADDR_ANY; |
---|
577 | |
---|
578 | bzero((caddr_t) &oldgw, sizeof(oldgw)); |
---|
579 | oldgw.sin_len=sizeof(oldgw); |
---|
580 | oldgw.sin_family=AF_INET; |
---|
581 | oldgw.sin_addr.s_addr = INADDR_ANY; |
---|
582 | |
---|
583 | bzero((caddr_t) &oldmask, sizeof(oldmask)); |
---|
584 | oldmask.sin_len=sizeof(oldmask); |
---|
585 | oldmask.sin_family=AF_INET; |
---|
586 | oldmask.sin_addr.s_addr = INADDR_ANY; |
---|
587 | |
---|
588 | error = rtrequest(RTM_DELETE, |
---|
589 | (struct sockaddr *) &olddst, |
---|
590 | (struct sockaddr *) &oldgw, |
---|
591 | (struct sockaddr *) &oldmask, |
---|
592 | (RTF_UP | RTF_STATIC), NULL); |
---|
593 | if (error) { |
---|
594 | printf("nfs_boot: del default route, error=%d\n", error); |
---|
595 | return error; |
---|
596 | } |
---|
597 | |
---|
598 | /* |
---|
599 | * Do enough of ifconfig(8) so that the chosen interface |
---|
600 | * can talk to the servers. (just set the address) |
---|
601 | */ |
---|
602 | bcopy(netmask,&ireq->ifr_addr,sizeof(*netmask)); |
---|
603 | error = ifioctl(so, SIOCSIFNETMASK, (caddr_t)ireq, procp); |
---|
604 | if (error) |
---|
605 | panic("nfs_boot: set if netmask, error=%d", error); |
---|
606 | |
---|
607 | /* Broadcast is with host part of IP address all 1's */ |
---|
608 | |
---|
609 | sin = (struct sockaddr_in *)&ireq->ifr_addr; |
---|
610 | bzero((caddr_t)sin, sizeof(*sin)); |
---|
611 | sin->sin_len = sizeof(*sin); |
---|
612 | sin->sin_family = AF_INET; |
---|
613 | sin->sin_addr.s_addr = myaddr->sin_addr.s_addr | ~ netmask->sin_addr.s_addr; |
---|
614 | error = ifioctl(so, SIOCSIFBRDADDR, (caddr_t)ireq, procp); |
---|
615 | if (error) |
---|
616 | panic("bootpc_call: set if broadcast addr, error=%d", error); |
---|
617 | |
---|
618 | bcopy(myaddr,&ireq->ifr_addr,sizeof(*myaddr)); |
---|
619 | error = ifioctl(so, SIOCSIFADDR, (caddr_t)ireq, procp); |
---|
620 | if (error) |
---|
621 | panic("nfs_boot: set if addr, error=%d", error); |
---|
622 | |
---|
623 | /* Add new default route */ |
---|
624 | |
---|
625 | error = rtrequest(RTM_ADD, |
---|
626 | (struct sockaddr *) &olddst, |
---|
627 | (struct sockaddr *) gw, |
---|
628 | (struct sockaddr *) &oldmask, |
---|
629 | (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL); |
---|
630 | if (error) { |
---|
631 | printf("nfs_boot: add net route, error=%d\n", error); |
---|
632 | return error; |
---|
633 | } |
---|
634 | |
---|
635 | return 0; |
---|
636 | } |
---|
637 | |
---|
638 | #if !defined(__rtems__) |
---|
639 | static int setfs(addr, path, p) |
---|
640 | struct sockaddr_in *addr; |
---|
641 | char *path; |
---|
642 | char *p; |
---|
643 | { |
---|
644 | unsigned ip = 0; |
---|
645 | int val; |
---|
646 | |
---|
647 | if (((val = getdec(&p)) < 0) || (val > 255)) return(0); |
---|
648 | ip = val << 24; |
---|
649 | if (*p != '.') return(0); |
---|
650 | p++; |
---|
651 | if (((val = getdec(&p)) < 0) || (val > 255)) return(0); |
---|
652 | ip |= (val << 16); |
---|
653 | if (*p != '.') return(0); |
---|
654 | p++; |
---|
655 | if (((val = getdec(&p)) < 0) || (val > 255)) return(0); |
---|
656 | ip |= (val << 8); |
---|
657 | if (*p != '.') return(0); |
---|
658 | p++; |
---|
659 | if (((val = getdec(&p)) < 0) || (val > 255)) return(0); |
---|
660 | ip |= val; |
---|
661 | if (*p != ':') return(0); |
---|
662 | p++; |
---|
663 | |
---|
664 | addr->sin_addr.s_addr = htonl(ip); |
---|
665 | addr->sin_len = sizeof(struct sockaddr_in); |
---|
666 | addr->sin_family = AF_INET; |
---|
667 | |
---|
668 | strncpy(path,p,MNAMELEN-1); |
---|
669 | return(1); |
---|
670 | } |
---|
671 | #endif |
---|
672 | |
---|
673 | #if !defined(__rtems__) |
---|
674 | static int getdec(ptr) |
---|
675 | char **ptr; |
---|
676 | { |
---|
677 | char *p = *ptr; |
---|
678 | int ret=0; |
---|
679 | if ((*p < '0') || (*p > '9')) return(-1); |
---|
680 | while ((*p >= '0') && (*p <= '9')) { |
---|
681 | ret = ret*10 + (*p - '0'); |
---|
682 | p++; |
---|
683 | } |
---|
684 | *ptr = p; |
---|
685 | return(ret); |
---|
686 | } |
---|
687 | #endif |
---|
688 | |
---|
689 | #if !defined(__rtems__) |
---|
690 | static char *substr(a,b) |
---|
691 | char *a,*b; |
---|
692 | { |
---|
693 | char *loc1; |
---|
694 | char *loc2; |
---|
695 | |
---|
696 | while (*a != '\0') { |
---|
697 | loc1 = a; |
---|
698 | loc2 = b; |
---|
699 | while (*loc1 == *loc2++) { |
---|
700 | if (*loc1 == '\0') return (0); |
---|
701 | loc1++; |
---|
702 | if (*loc2 == '\0') return (loc1); |
---|
703 | } |
---|
704 | a++; |
---|
705 | } |
---|
706 | return (0); |
---|
707 | } |
---|
708 | #endif |
---|
709 | |
---|
710 | static void printip(char *prefix,struct in_addr addr) |
---|
711 | { |
---|
712 | unsigned int ip; |
---|
713 | |
---|
714 | ip = ntohl(addr.s_addr); |
---|
715 | |
---|
716 | printf("%s is %d.%d.%d.%d\n",prefix, |
---|
717 | ip >> 24, (ip >> 16) & 255 ,(ip >> 8) & 255 ,ip & 255 ); |
---|
718 | } |
---|
719 | |
---|
720 | static int dhcpOptionOverload = 0; |
---|
721 | static char dhcp_gotgw = 0; |
---|
722 | static char dhcp_gotnetmask = 0; |
---|
723 | static char dhcp_gotserver = 0; |
---|
724 | static char dhcp_gotlogserver = 0; |
---|
725 | static struct sockaddr_in dhcp_netmask; |
---|
726 | static struct sockaddr_in dhcp_gw; |
---|
727 | static char *dhcp_hostname = NULL; |
---|
728 | |
---|
729 | static void |
---|
730 | processOptions (unsigned char *optbuf, int optbufSize) |
---|
731 | { |
---|
732 | int j = 0; |
---|
733 | int len; |
---|
734 | int code, ncode; |
---|
735 | char *p; |
---|
736 | |
---|
737 | ncode = optbuf[0]; |
---|
738 | while (j < optbufSize) { |
---|
739 | code = optbuf[j] = ncode; |
---|
740 | if (code == 255) |
---|
741 | return; |
---|
742 | if (code == 0) { |
---|
743 | j++; |
---|
744 | continue; |
---|
745 | } |
---|
746 | len = optbuf[j+1]; |
---|
747 | j += 2; |
---|
748 | if ((len + j) >= optbufSize) { |
---|
749 | printf ("Truncated field for code %d", code); |
---|
750 | return; |
---|
751 | } |
---|
752 | ncode = optbuf[j+len]; |
---|
753 | optbuf[j+len] = '\0'; |
---|
754 | p = &optbuf[j]; |
---|
755 | j += len; |
---|
756 | |
---|
757 | /* |
---|
758 | * Process the option |
---|
759 | */ |
---|
760 | switch (code) { |
---|
761 | case 1: |
---|
762 | /* Subnet mask */ |
---|
763 | if (len!=4) |
---|
764 | panic("bootpc: subnet mask len is %d",len); |
---|
765 | bcopy (p, &dhcp_netmask.sin_addr, 4); |
---|
766 | dhcp_gotnetmask = 1; |
---|
767 | break; |
---|
768 | |
---|
769 | case 2: |
---|
770 | /* Time offset */ |
---|
771 | if (len!=4) |
---|
772 | panic("bootpc: time offset len is %d",len); |
---|
773 | bcopy (p, &rtems_bsdnet_timeoffset, 4); |
---|
774 | rtems_bsdnet_timeoffset = ntohl (rtems_bsdnet_timeoffset); |
---|
775 | break; |
---|
776 | |
---|
777 | case 3: |
---|
778 | /* Routers */ |
---|
779 | if (len % 4) |
---|
780 | panic ("bootpc: Router Len is %d", len); |
---|
781 | if (len > 0) { |
---|
782 | bcopy(p, &dhcp_gw.sin_addr, 4); |
---|
783 | dhcp_gotgw = 1; |
---|
784 | } |
---|
785 | break; |
---|
786 | |
---|
787 | case 42: |
---|
788 | /* NTP servers */ |
---|
789 | if (len % 4) |
---|
790 | panic ("bootpc: time server Len is %d", len); |
---|
791 | { |
---|
792 | int tlen = 0; |
---|
793 | while ((tlen < len) && |
---|
794 | (rtems_bsdnet_ntpserver_count < sizeof rtems_bsdnet_config.ntp_server / |
---|
795 | sizeof rtems_bsdnet_config.ntp_server[0])) { |
---|
796 | bcopy (p+tlen, |
---|
797 | &rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count], |
---|
798 | 4); |
---|
799 | printip("Time Server", |
---|
800 | rtems_bsdnet_ntpserver[rtems_bsdnet_ntpserver_count]); |
---|
801 | rtems_bsdnet_ntpserver_count++; |
---|
802 | tlen += 4; |
---|
803 | } |
---|
804 | } |
---|
805 | break; |
---|
806 | |
---|
807 | case 6: |
---|
808 | /* Domain Name servers */ |
---|
809 | if (len % 4) |
---|
810 | panic ("bootpc: DNS Len is %d", len); |
---|
811 | { |
---|
812 | int dlen = 0; |
---|
813 | while ((dlen < len) && |
---|
814 | (rtems_bsdnet_nameserver_count < sizeof rtems_bsdnet_config.name_server / |
---|
815 | sizeof rtems_bsdnet_config.name_server[0])) { |
---|
816 | bcopy (p+dlen, |
---|
817 | &rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count], |
---|
818 | 4); |
---|
819 | printip("Domain Name Server", |
---|
820 | rtems_bsdnet_nameserver[rtems_bsdnet_nameserver_count]); |
---|
821 | rtems_bsdnet_nameserver_count++; |
---|
822 | dlen += 4; |
---|
823 | } |
---|
824 | } |
---|
825 | break; |
---|
826 | |
---|
827 | case 12: |
---|
828 | /* Host name */ |
---|
829 | if (len>=MAXHOSTNAMELEN) |
---|
830 | panic ("bootpc: hostname >=%d bytes", MAXHOSTNAMELEN); |
---|
831 | if (sethostname (p, len) < 0) |
---|
832 | panic("Can't set host name"); |
---|
833 | printf("Hostname is %s\n", p); |
---|
834 | dhcp_hostname = bootp_strdup_realloc(dhcp_hostname,p); |
---|
835 | break; |
---|
836 | |
---|
837 | case 7: |
---|
838 | /* Log servers */ |
---|
839 | if (len % 4) |
---|
840 | panic ("bootpc: Log server Len is %d", len); |
---|
841 | if (len > 0) { |
---|
842 | bcopy(p, &rtems_bsdnet_log_host_address, 4); |
---|
843 | dhcp_gotlogserver = 1; |
---|
844 | } |
---|
845 | break; |
---|
846 | |
---|
847 | case 15: |
---|
848 | /* Domain name */ |
---|
849 | if (p[0]) { |
---|
850 | rtems_bsdnet_domain_name = |
---|
851 | bootp_strdup_realloc(rtems_bsdnet_domain_name,p); |
---|
852 | printf("Domain name is %s\n", rtems_bsdnet_domain_name); |
---|
853 | } |
---|
854 | break; |
---|
855 | |
---|
856 | case 16: /* Swap server IP address. unused */ |
---|
857 | break; |
---|
858 | |
---|
859 | case 52: |
---|
860 | /* DHCP option override */ |
---|
861 | if (len != 1) |
---|
862 | panic ("bootpc: DHCP option overload len is %d", len); |
---|
863 | dhcpOptionOverload = p[0]; |
---|
864 | break; |
---|
865 | |
---|
866 | case 128: /* Site-specific option for DHCP servers that |
---|
867 | * a) don't supply tag 54 |
---|
868 | * and |
---|
869 | * b) don't supply the server address in siaddr |
---|
870 | * For example, on Solaris 2.6 in.dhcpd, include in the dhcptab: |
---|
871 | * Bootsrv s Site,128,IP,1,1 |
---|
872 | * and use that symbol in the macro that defines the client: |
---|
873 | * Bootsrv=<tftp-server-ip-address> |
---|
874 | */ |
---|
875 | case 54: |
---|
876 | /* DHCP server */ |
---|
877 | if (len != 4) |
---|
878 | panic ("bootpc: DHCP server len is %d", len); |
---|
879 | bcopy(p, &rtems_bsdnet_bootp_server_address, 4); |
---|
880 | dhcp_gotserver = 1; |
---|
881 | break; |
---|
882 | |
---|
883 | case 66: |
---|
884 | /* DHCP server name option */ |
---|
885 | if (p[0]) |
---|
886 | rtems_bsdnet_bootp_server_name = |
---|
887 | bootp_strdup_realloc(rtems_bsdnet_bootp_server_name,p); |
---|
888 | break; |
---|
889 | |
---|
890 | case 67: |
---|
891 | /* DHCP bootfile option */ |
---|
892 | if (p[0]) |
---|
893 | rtems_bsdnet_bootp_boot_file_name = |
---|
894 | bootp_strdup_realloc(rtems_bsdnet_bootp_boot_file_name,p); |
---|
895 | break; |
---|
896 | |
---|
897 | default: |
---|
898 | printf ("Ignoring BOOTP/DHCP option code %d\n", code); |
---|
899 | break; |
---|
900 | } |
---|
901 | } |
---|
902 | } |
---|
903 | |
---|
904 | #define EALEN 6 |
---|
905 | |
---|
906 | void |
---|
907 | bootpc_init(int update_files) |
---|
908 | { |
---|
909 | struct bootp_packet call; |
---|
910 | struct bootp_packet reply; |
---|
911 | static u_int32_t xid = ~0xFF; |
---|
912 | |
---|
913 | struct ifreq ireq; |
---|
914 | struct ifnet *ifp; |
---|
915 | struct socket *so; |
---|
916 | int j; |
---|
917 | int error; |
---|
918 | struct sockaddr_in myaddr; |
---|
919 | struct ifaddr *ifa; |
---|
920 | struct sockaddr_dl *sdl = NULL; |
---|
921 | char *delim; |
---|
922 | struct proc *procp = NULL; |
---|
923 | |
---|
924 | /* |
---|
925 | * If already filled in, don't touch it here |
---|
926 | */ |
---|
927 | if (nfs_diskless_valid) |
---|
928 | return; |
---|
929 | |
---|
930 | /* |
---|
931 | * If we are to update the files create the root |
---|
932 | * file structure. |
---|
933 | */ |
---|
934 | if (update_files) |
---|
935 | if (rtems_create_root_fs () < 0) { |
---|
936 | printf("Error creating the root filesystem.\nFile not created.\n"); |
---|
937 | update_files = 0; |
---|
938 | } |
---|
939 | |
---|
940 | dhcp_hostname = NULL; |
---|
941 | |
---|
942 | /* |
---|
943 | * Find a network interface. |
---|
944 | */ |
---|
945 | for (ifp = ifnet; ifp != 0; ifp = ifp->if_next) |
---|
946 | if ((ifp->if_flags & |
---|
947 | (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0) |
---|
948 | break; |
---|
949 | if (ifp == NULL) |
---|
950 | panic("bootpc_init: no suitable interface"); |
---|
951 | bzero(&ireq,sizeof(ireq)); |
---|
952 | sprintf(ireq.ifr_name, "%s%d", ifp->if_name,ifp->if_unit); |
---|
953 | printf("bootpc_init: using network interface '%s'\n", |
---|
954 | ireq.ifr_name); |
---|
955 | |
---|
956 | if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,procp)) != 0) |
---|
957 | panic("nfs_boot: socreate, error=%d", error); |
---|
958 | |
---|
959 | bootpc_fakeup_interface(&ireq,so,procp); |
---|
960 | |
---|
961 | printf("Bootpc testing starting\n"); |
---|
962 | |
---|
963 | /* Get HW address */ |
---|
964 | |
---|
965 | for (ifa = ifp->if_addrlist;ifa; ifa = ifa->ifa_next) |
---|
966 | if (ifa->ifa_addr->sa_family == AF_LINK && |
---|
967 | (sdl = ((struct sockaddr_dl *) ifa->ifa_addr)) && |
---|
968 | sdl->sdl_type == IFT_ETHER) |
---|
969 | break; |
---|
970 | |
---|
971 | if (!sdl) |
---|
972 | panic("bootpc: Unable to find HW address"); |
---|
973 | if (sdl->sdl_alen != EALEN ) |
---|
974 | panic("bootpc: HW address len is %d, expected value is %d", |
---|
975 | sdl->sdl_alen,EALEN); |
---|
976 | |
---|
977 | printf("bootpc hw address is "); |
---|
978 | delim=""; |
---|
979 | for (j=0;j<sdl->sdl_alen;j++) { |
---|
980 | printf("%s%x",delim,((unsigned char *)LLADDR(sdl))[j]); |
---|
981 | delim=":"; |
---|
982 | } |
---|
983 | printf("\n"); |
---|
984 | |
---|
985 | #if 0 |
---|
986 | bootpboot_p_iflist(); |
---|
987 | bootpboot_p_rtlist(); |
---|
988 | #endif |
---|
989 | |
---|
990 | bzero((caddr_t) &call, sizeof(call)); |
---|
991 | |
---|
992 | /* bootpc part */ |
---|
993 | call.op = 1; /* BOOTREQUEST */ |
---|
994 | call.htype= 1; /* 10mb ethernet */ |
---|
995 | call.hlen=sdl->sdl_alen; /* Hardware address length */ |
---|
996 | call.hops=0; |
---|
997 | xid++; |
---|
998 | call.xid = txdr_unsigned(xid); |
---|
999 | bcopy(LLADDR(sdl),&call.chaddr,sdl->sdl_alen); |
---|
1000 | |
---|
1001 | call.vend[0]=99; |
---|
1002 | call.vend[1]=130; |
---|
1003 | call.vend[2]=83; |
---|
1004 | call.vend[3]=99; |
---|
1005 | call.vend[4]=255; |
---|
1006 | |
---|
1007 | call.secs = 0; |
---|
1008 | call.flags = htons(0x8000); /* We need an broadcast answer */ |
---|
1009 | |
---|
1010 | error = bootpc_call(&call,&reply,procp); |
---|
1011 | |
---|
1012 | if (error) |
---|
1013 | panic("BOOTP call failed -- error %d", error); |
---|
1014 | |
---|
1015 | /* |
---|
1016 | * Initialize network address structures |
---|
1017 | */ |
---|
1018 | bzero(&myaddr,sizeof(myaddr)); |
---|
1019 | bzero(&dhcp_netmask,sizeof(dhcp_netmask)); |
---|
1020 | bzero(&dhcp_gw,sizeof(dhcp_gw)); |
---|
1021 | myaddr.sin_len = sizeof(myaddr); |
---|
1022 | myaddr.sin_family = AF_INET; |
---|
1023 | dhcp_netmask.sin_len = sizeof(dhcp_netmask); |
---|
1024 | dhcp_netmask.sin_family = AF_INET; |
---|
1025 | dhcp_gw.sin_len = sizeof(dhcp_gw); |
---|
1026 | dhcp_gw.sin_family= AF_INET; |
---|
1027 | |
---|
1028 | /* |
---|
1029 | * Set our address |
---|
1030 | */ |
---|
1031 | myaddr.sin_addr = reply.yiaddr; |
---|
1032 | printip("My ip address",myaddr.sin_addr); |
---|
1033 | |
---|
1034 | /* |
---|
1035 | * Process BOOTP/DHCP options |
---|
1036 | */ |
---|
1037 | if (reply.vend[0]==99 && reply.vend[1]==130 && |
---|
1038 | reply.vend[2]==83 && reply.vend[3]==99) { |
---|
1039 | processOptions (&reply.vend[4], sizeof(reply.vend) - 4); |
---|
1040 | } |
---|
1041 | if (dhcpOptionOverload & 1) { |
---|
1042 | processOptions (reply.file, sizeof reply.file); |
---|
1043 | } |
---|
1044 | else { |
---|
1045 | if (reply.file[0]) |
---|
1046 | rtems_bsdnet_bootp_boot_file_name = |
---|
1047 | bootp_strdup_realloc(rtems_bsdnet_bootp_boot_file_name,reply.file); |
---|
1048 | } |
---|
1049 | if (dhcpOptionOverload & 2) { |
---|
1050 | processOptions (reply.sname, sizeof reply.sname); |
---|
1051 | } |
---|
1052 | else { |
---|
1053 | if (reply.sname[0]) |
---|
1054 | rtems_bsdnet_bootp_server_name = |
---|
1055 | bootp_strdup_realloc(rtems_bsdnet_bootp_server_name,reply.sname); |
---|
1056 | } |
---|
1057 | if (rtems_bsdnet_bootp_server_name) |
---|
1058 | printf ("Server name is %s\n", rtems_bsdnet_bootp_server_name); |
---|
1059 | if (rtems_bsdnet_bootp_boot_file_name) |
---|
1060 | printf ("Boot file is %s\n", rtems_bsdnet_bootp_boot_file_name); |
---|
1061 | |
---|
1062 | /* |
---|
1063 | * Use defaults if values were not supplied by BOOTP/DHCP options |
---|
1064 | */ |
---|
1065 | if (!dhcp_gotnetmask) { |
---|
1066 | if (IN_CLASSA(ntohl(myaddr.sin_addr.s_addr))) |
---|
1067 | dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET); |
---|
1068 | else if (IN_CLASSB(ntohl(myaddr.sin_addr.s_addr))) |
---|
1069 | dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET); |
---|
1070 | else |
---|
1071 | dhcp_netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET); |
---|
1072 | } |
---|
1073 | printip ("Subnet mask", dhcp_netmask.sin_addr); |
---|
1074 | if (!dhcp_gotserver) |
---|
1075 | rtems_bsdnet_bootp_server_address = reply.siaddr; |
---|
1076 | printip ("Server ip address" ,rtems_bsdnet_bootp_server_address); |
---|
1077 | if (!dhcp_gotgw) |
---|
1078 | dhcp_gw.sin_addr = reply.giaddr; |
---|
1079 | printip ("Gateway ip address", dhcp_gw.sin_addr); |
---|
1080 | if (!dhcp_gotlogserver) |
---|
1081 | rtems_bsdnet_log_host_address = rtems_bsdnet_bootp_server_address; |
---|
1082 | printip ("Log server ip address", rtems_bsdnet_log_host_address); |
---|
1083 | |
---|
1084 | /* |
---|
1085 | * Update the files if we are asked too. |
---|
1086 | */ |
---|
1087 | if (update_files) { |
---|
1088 | char *dn = rtems_bsdnet_domain_name; |
---|
1089 | char *hn = dhcp_hostname; |
---|
1090 | if (!dn) |
---|
1091 | dn = "mydomain"; |
---|
1092 | if (!hn) |
---|
1093 | hn = "me"; |
---|
1094 | rtems_rootfs_append_host_rec(*((unsigned long*) &myaddr.sin_addr), hn, dn); |
---|
1095 | |
---|
1096 | /* |
---|
1097 | * Should the given domainname be used here ? |
---|
1098 | */ |
---|
1099 | if (dhcp_gotserver) { |
---|
1100 | if (rtems_bsdnet_bootp_server_name) |
---|
1101 | hn = rtems_bsdnet_bootp_server_name; |
---|
1102 | else |
---|
1103 | hn = "bootps"; |
---|
1104 | rtems_rootfs_append_host_rec(*((unsigned long *) &rtems_bsdnet_bootp_server_address), |
---|
1105 | hn, dn); |
---|
1106 | } |
---|
1107 | |
---|
1108 | if (dhcp_gotlogserver) { |
---|
1109 | rtems_rootfs_append_host_rec(*((unsigned long *) &rtems_bsdnet_log_host_address), |
---|
1110 | "logs", dn); |
---|
1111 | } |
---|
1112 | |
---|
1113 | /* |
---|
1114 | * Setup the DNS configuration file /etc/resolv.conf. |
---|
1115 | */ |
---|
1116 | if (rtems_bsdnet_nameserver_count) { |
---|
1117 | int i; |
---|
1118 | char buf[64]; |
---|
1119 | const char *bufl[1]; |
---|
1120 | |
---|
1121 | bufl[0] = buf; |
---|
1122 | |
---|
1123 | #define MKFILE_MODE (S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH) |
---|
1124 | |
---|
1125 | if (rtems_bsdnet_domain_name && |
---|
1126 | (strlen(rtems_bsdnet_domain_name) < (sizeof(buf) - 1))) { |
---|
1127 | strcpy(buf, "search "); |
---|
1128 | strcat(buf, rtems_bsdnet_domain_name); |
---|
1129 | strcat(buf, "\n"); |
---|
1130 | rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl); |
---|
1131 | } |
---|
1132 | |
---|
1133 | for (i = 0; i < rtems_bsdnet_nameserver_count; i++) { |
---|
1134 | strcpy(buf, "nameserver "); |
---|
1135 | strcat(buf, inet_ntoa(rtems_bsdnet_ntpserver[i])); |
---|
1136 | strcat(buf, "\n"); |
---|
1137 | if (rtems_rootfs_file_append ("/etc/resolv.conf", MKFILE_MODE, 1, bufl)) |
---|
1138 | break; |
---|
1139 | } |
---|
1140 | } |
---|
1141 | } |
---|
1142 | |
---|
1143 | /* |
---|
1144 | * Configure the interface with the new settings |
---|
1145 | */ |
---|
1146 | error = bootpc_adjust_interface(&ireq,so, |
---|
1147 | &myaddr,&dhcp_netmask,&dhcp_gw,procp); |
---|
1148 | soclose(so); |
---|
1149 | } |
---|