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