FreeBSD/Linux Kernel Cross Reference
sys/nfs/bootp_subr.c
1 /*-
2 * Copyright (c) 1995 Gordon Ross, Adam Glass
3 * Copyright (c) 1992 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This software was developed by the Computer Systems Engineering group
7 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
8 * contributed to Berkeley.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Lawrence Berkeley Laboratory and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * based on:
39 * nfs/krpc_subr.c
40 * $NetBSD: krpc_subr.c,v 1.10 1995/08/08 20:43:43 gwr Exp $
41 */
42
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 #include "opt_bootp.h"
47 #include "opt_nfs.h"
48 #include "opt_rootdevname.h"
49
50 #include <sys/param.h>
51 #include <sys/systm.h>
52 #include <sys/endian.h>
53 #include <sys/jail.h>
54 #include <sys/kernel.h>
55 #include <sys/sockio.h>
56 #include <sys/malloc.h>
57 #include <sys/mount.h>
58 #include <sys/mbuf.h>
59 #include <sys/proc.h>
60 #include <sys/reboot.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/sysctl.h>
64 #include <sys/uio.h>
65
66 #include <net/if.h>
67 #include <net/route.h>
68
69 #include <netinet/in.h>
70 #include <netinet/in_var.h>
71 #include <net/if_types.h>
72 #include <net/if_dl.h>
73 #include <net/vnet.h>
74
75 #include <nfs/nfsproto.h>
76 #include <nfsclient/nfs.h>
77 #include <nfs/nfsdiskless.h>
78 #include <nfs/krpc.h>
79 #include <nfs/xdr_subs.h>
80
81
82 #define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */
83
84 #ifndef BOOTP_SETTLE_DELAY
85 #define BOOTP_SETTLE_DELAY 3
86 #endif
87
88 /*
89 * Wait 10 seconds for interface appearance
90 * USB ethernet adapters might require some time to pop up
91 */
92 #ifndef BOOTP_IFACE_WAIT_TIMEOUT
93 #define BOOTP_IFACE_WAIT_TIMEOUT 10
94 #endif
95
96 /*
97 * What is the longest we will wait before re-sending a request?
98 * Note this is also the frequency of "RPC timeout" messages.
99 * The re-send loop count sup linearly to this maximum, so the
100 * first complaint will happen after (1+2+3+4+5)=15 seconds.
101 */
102 #define MAX_RESEND_DELAY 5 /* seconds */
103
104 /* Definitions from RFC951 */
105 struct bootp_packet {
106 u_int8_t op;
107 u_int8_t htype;
108 u_int8_t hlen;
109 u_int8_t hops;
110 u_int32_t xid;
111 u_int16_t secs;
112 u_int16_t flags;
113 struct in_addr ciaddr;
114 struct in_addr yiaddr;
115 struct in_addr siaddr;
116 struct in_addr giaddr;
117 unsigned char chaddr[16];
118 char sname[64];
119 char file[128];
120 unsigned char vend[1222];
121 };
122
123 struct bootpc_ifcontext {
124 STAILQ_ENTRY(bootpc_ifcontext) next;
125 struct bootp_packet call;
126 struct bootp_packet reply;
127 int replylen;
128 int overload;
129 union {
130 struct ifreq _ifreq;
131 struct in_aliasreq _in_alias_req;
132 } _req;
133 #define ireq _req._ifreq
134 #define iareq _req._in_alias_req
135 struct ifnet *ifp;
136 struct sockaddr_dl *sdl;
137 struct sockaddr_in myaddr;
138 struct sockaddr_in netmask;
139 struct sockaddr_in gw;
140 int gotgw;
141 int gotnetmask;
142 int gotrootpath;
143 int outstanding;
144 int sentmsg;
145 u_int32_t xid;
146 enum {
147 IF_BOOTP_UNRESOLVED,
148 IF_BOOTP_RESOLVED,
149 IF_BOOTP_FAILED,
150 IF_DHCP_UNRESOLVED,
151 IF_DHCP_OFFERED,
152 IF_DHCP_RESOLVED,
153 IF_DHCP_FAILED,
154 } state;
155 int dhcpquerytype; /* dhcp type sent */
156 struct in_addr dhcpserver;
157 int gotdhcpserver;
158 uint16_t mtu;
159 };
160
161 #define TAG_MAXLEN 1024
162 struct bootpc_tagcontext {
163 char buf[TAG_MAXLEN + 1];
164 int overload;
165 int badopt;
166 int badtag;
167 int foundopt;
168 int taglen;
169 };
170
171 struct bootpc_globalcontext {
172 STAILQ_HEAD(, bootpc_ifcontext) interfaces;
173 u_int32_t xid;
174 int any_root_overrides;
175 int gotrootpath;
176 int gotgw;
177 int ifnum;
178 int secs;
179 int starttime;
180 struct bootp_packet reply;
181 int replylen;
182 struct bootpc_ifcontext *setrootfs;
183 struct bootpc_ifcontext *sethostname;
184 struct bootpc_tagcontext tmptag;
185 struct bootpc_tagcontext tag;
186 };
187
188 #define IPPORT_BOOTPC 68
189 #define IPPORT_BOOTPS 67
190
191 #define BOOTP_REQUEST 1
192 #define BOOTP_REPLY 2
193
194 /* Common tags */
195 #define TAG_PAD 0 /* Pad option, implicit length 1 */
196 #define TAG_SUBNETMASK 1 /* RFC 950 subnet mask */
197 #define TAG_ROUTERS 3 /* Routers (in order of preference) */
198 #define TAG_HOSTNAME 12 /* Client host name */
199 #define TAG_ROOT 17 /* Root path */
200 #define TAG_INTF_MTU 26 /* Interface MTU Size (RFC2132) */
201
202 /* DHCP specific tags */
203 #define TAG_OVERLOAD 52 /* Option Overload */
204 #define TAG_MAXMSGSIZE 57 /* Maximum DHCP Message Size */
205
206 #define TAG_END 255 /* End Option (i.e. no more options) */
207
208 /* Overload values */
209 #define OVERLOAD_FILE 1
210 #define OVERLOAD_SNAME 2
211
212 /* Site specific tags: */
213 #define TAG_ROOTOPTS 130
214 #define TAG_COOKIE 134 /* ascii info for userland, via sysctl */
215
216 #define TAG_DHCP_MSGTYPE 53
217 #define TAG_DHCP_REQ_ADDR 50
218 #define TAG_DHCP_SERVERID 54
219 #define TAG_DHCP_LEASETIME 51
220
221 #define TAG_VENDOR_INDENTIFIER 60
222
223 #define DHCP_NOMSG 0
224 #define DHCP_DISCOVER 1
225 #define DHCP_OFFER 2
226 #define DHCP_REQUEST 3
227 #define DHCP_ACK 5
228
229 /* NFS read/write block size */
230 #ifndef BOOTP_BLOCKSIZE
231 #define BOOTP_BLOCKSIZE 8192
232 #endif
233
234 static char bootp_cookie[128];
235 static struct socket *bootp_so;
236 SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD,
237 bootp_cookie, 0, "Cookie (T134) supplied by bootp server");
238
239 /* mountd RPC */
240 static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp,
241 int *fhsizep, struct nfs_args *args, struct thread *td);
242 static int setfs(struct sockaddr_in *addr, char *path, char *p,
243 const struct in_addr *siaddr);
244 static int getdec(char **ptr);
245 static int getip(char **ptr, struct in_addr *ip);
246 static void mountopts(struct nfs_args *args, char *p);
247 static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
248 static int xdr_int_decode(struct mbuf **ptr, int *iptr);
249 static void print_in_addr(struct in_addr addr);
250 static void print_sin_addr(struct sockaddr_in *addr);
251 static void clear_sinaddr(struct sockaddr_in *sin);
252 static void allocifctx(struct bootpc_globalcontext *gctx);
253 static void bootpc_compose_query(struct bootpc_ifcontext *ifctx,
254 struct thread *td);
255 static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx,
256 struct bootp_packet *bp, int len, int tag);
257 static void bootpc_tag_helper(struct bootpc_tagcontext *tctx,
258 unsigned char *start, int len, int tag);
259
260 #ifdef BOOTP_DEBUG
261 void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma);
262 void bootpboot_p_rtentry(struct rtentry *rt);
263 void bootpboot_p_tree(struct radix_node *rn);
264 void bootpboot_p_rtlist(void);
265 void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa);
266 void bootpboot_p_iflist(void);
267 #endif
268
269 static int bootpc_call(struct bootpc_globalcontext *gctx,
270 struct thread *td);
271
272 static void bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
273 struct thread *td);
274
275 static void bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
276 struct bootpc_globalcontext *gctx, struct thread *td);
277
278 static void bootpc_decode_reply(struct nfsv3_diskless *nd,
279 struct bootpc_ifcontext *ifctx,
280 struct bootpc_globalcontext *gctx);
281
282 static int bootpc_received(struct bootpc_globalcontext *gctx,
283 struct bootpc_ifcontext *ifctx);
284
285 static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx);
286 static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx);
287 static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx);
288
289 /*
290 * In order to have multiple active interfaces with address 0.0.0.0
291 * and be able to send data to a selected interface, we first set
292 * mask to /8 on all interfaces, and temporarily set it to /0 when
293 * doing sosend().
294 */
295
296 #ifdef BOOTP_DEBUG
297 void
298 bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma)
299 {
300
301 if (sa == NULL) {
302 printf("(sockaddr *) <null>");
303 return;
304 }
305 switch (sa->sa_family) {
306 case AF_INET:
307 {
308 struct sockaddr_in *sin;
309
310 sin = (struct sockaddr_in *) sa;
311 printf("inet ");
312 print_sin_addr(sin);
313 if (ma != NULL) {
314 sin = (struct sockaddr_in *) ma;
315 printf(" mask ");
316 print_sin_addr(sin);
317 }
318 }
319 break;
320 case AF_LINK:
321 {
322 struct sockaddr_dl *sli;
323 int i;
324
325 sli = (struct sockaddr_dl *) sa;
326 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data);
327 for (i = 0; i < sli->sdl_alen; i++) {
328 if (i > 0)
329 printf(":");
330 printf("%x", ((unsigned char *) LLADDR(sli))[i]);
331 }
332 }
333 break;
334 default:
335 printf("af%d", sa->sa_family);
336 }
337 }
338
339 void
340 bootpboot_p_rtentry(struct rtentry *rt)
341 {
342
343 bootpboot_p_sa(rt_key(rt), rt_mask(rt));
344 printf(" ");
345 bootpboot_p_sa(rt->rt_gateway, NULL);
346 printf(" ");
347 printf("flags %x", (unsigned short) rt->rt_flags);
348 printf(" %d", (int) rt->rt_expire);
349 printf(" %s\n", rt->rt_ifp->if_xname);
350 }
351
352 void
353 bootpboot_p_tree(struct radix_node *rn)
354 {
355
356 while (rn != NULL) {
357 if (rn->rn_bit < 0) {
358 if ((rn->rn_flags & RNF_ROOT) != 0) {
359 } else {
360 bootpboot_p_rtentry((struct rtentry *) rn);
361 }
362 rn = rn->rn_dupedkey;
363 } else {
364 bootpboot_p_tree(rn->rn_left);
365 bootpboot_p_tree(rn->rn_right);
366 return;
367 }
368 }
369 }
370
371 void
372 bootpboot_p_rtlist(void)
373 {
374 struct radix_node_head *rnh;
375
376 printf("Routing table:\n");
377 rnh = rt_tables_get_rnh(0, AF_INET);
378 if (rnh == NULL)
379 return;
380 RADIX_NODE_HEAD_RLOCK(rnh); /* could sleep XXX */
381 bootpboot_p_tree(rnh->rnh_treetop);
382 RADIX_NODE_HEAD_RUNLOCK(rnh);
383 }
384
385 void
386 bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa)
387 {
388
389 printf("%s flags %x, addr ",
390 ifp->if_xname, ifp->if_flags);
391 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr);
392 printf(", broadcast ");
393 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr);
394 printf(", netmask ");
395 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask);
396 printf("\n");
397 }
398
399 void
400 bootpboot_p_iflist(void)
401 {
402 struct ifnet *ifp;
403 struct ifaddr *ifa;
404
405 printf("Interface list:\n");
406 IFNET_RLOCK();
407 for (ifp = TAILQ_FIRST(&V_ifnet);
408 ifp != NULL;
409 ifp = TAILQ_NEXT(ifp, if_link)) {
410 for (ifa = TAILQ_FIRST(&ifp->if_addrhead);
411 ifa != NULL;
412 ifa = TAILQ_NEXT(ifa, ifa_link))
413 if (ifa->ifa_addr->sa_family == AF_INET)
414 bootpboot_p_if(ifp, ifa);
415 }
416 IFNET_RUNLOCK();
417 }
418 #endif /* defined(BOOTP_DEBUG) */
419
420 static void
421 clear_sinaddr(struct sockaddr_in *sin)
422 {
423
424 bzero(sin, sizeof(*sin));
425 sin->sin_len = sizeof(*sin);
426 sin->sin_family = AF_INET;
427 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */
428 sin->sin_port = 0;
429 }
430
431 static void
432 allocifctx(struct bootpc_globalcontext *gctx)
433 {
434 struct bootpc_ifcontext *ifctx;
435
436 ifctx = malloc(sizeof(*ifctx), M_TEMP, M_WAITOK | M_ZERO);
437 ifctx->xid = gctx->xid;
438 #ifdef BOOTP_NO_DHCP
439 ifctx->state = IF_BOOTP_UNRESOLVED;
440 #else
441 ifctx->state = IF_DHCP_UNRESOLVED;
442 #endif
443 gctx->xid += 0x100;
444 STAILQ_INSERT_TAIL(&gctx->interfaces, ifctx, next);
445 }
446
447 static __inline int
448 bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx)
449 {
450
451 if (ifctx->state == IF_BOOTP_RESOLVED ||
452 ifctx->state == IF_DHCP_RESOLVED)
453 return 1;
454 return 0;
455 }
456
457 static __inline int
458 bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx)
459 {
460
461 if (ifctx->state == IF_BOOTP_UNRESOLVED ||
462 ifctx->state == IF_DHCP_UNRESOLVED)
463 return 1;
464 return 0;
465 }
466
467 static __inline int
468 bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx)
469 {
470
471 if (ifctx->state == IF_BOOTP_FAILED ||
472 ifctx->state == IF_DHCP_FAILED)
473 return 1;
474 return 0;
475 }
476
477 static int
478 bootpc_received(struct bootpc_globalcontext *gctx,
479 struct bootpc_ifcontext *ifctx)
480 {
481 unsigned char dhcpreplytype;
482 char *p;
483
484 /*
485 * Need timeout for fallback to less
486 * desirable alternative.
487 */
488
489 /* This call used for the side effect (badopt flag) */
490 (void) bootpc_tag(&gctx->tmptag, &gctx->reply,
491 gctx->replylen,
492 TAG_END);
493
494 /* If packet is invalid, ignore it */
495 if (gctx->tmptag.badopt != 0)
496 return 0;
497
498 p = bootpc_tag(&gctx->tmptag, &gctx->reply,
499 gctx->replylen, TAG_DHCP_MSGTYPE);
500 if (p != NULL)
501 dhcpreplytype = *p;
502 else
503 dhcpreplytype = DHCP_NOMSG;
504
505 switch (ifctx->dhcpquerytype) {
506 case DHCP_DISCOVER:
507 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */
508 #ifndef BOOTP_FORCE_DHCP
509 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */
510 #endif
511 )
512 return 0;
513 break;
514 case DHCP_REQUEST:
515 if (dhcpreplytype != DHCP_ACK)
516 return 0;
517 case DHCP_NOMSG:
518 break;
519 }
520
521 /* Ignore packet unless it gives us a root tag we didn't have */
522
523 if ((ifctx->state == IF_BOOTP_RESOLVED ||
524 (ifctx->dhcpquerytype == DHCP_DISCOVER &&
525 (ifctx->state == IF_DHCP_OFFERED ||
526 ifctx->state == IF_DHCP_RESOLVED))) &&
527 (bootpc_tag(&gctx->tmptag, &ifctx->reply,
528 ifctx->replylen,
529 TAG_ROOT) != NULL ||
530 bootpc_tag(&gctx->tmptag, &gctx->reply,
531 gctx->replylen,
532 TAG_ROOT) == NULL))
533 return 0;
534
535 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen);
536 ifctx->replylen = gctx->replylen;
537
538 /* XXX: Only reset if 'perfect' response */
539 if (ifctx->state == IF_BOOTP_UNRESOLVED)
540 ifctx->state = IF_BOOTP_RESOLVED;
541 else if (ifctx->state == IF_DHCP_UNRESOLVED &&
542 ifctx->dhcpquerytype == DHCP_DISCOVER) {
543 if (dhcpreplytype == DHCP_OFFER)
544 ifctx->state = IF_DHCP_OFFERED;
545 else
546 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */
547 } else if (ifctx->state == IF_DHCP_OFFERED &&
548 ifctx->dhcpquerytype == DHCP_REQUEST)
549 ifctx->state = IF_DHCP_RESOLVED;
550
551
552 if (ifctx->dhcpquerytype == DHCP_DISCOVER &&
553 ifctx->state != IF_BOOTP_RESOLVED) {
554 p = bootpc_tag(&gctx->tmptag, &ifctx->reply,
555 ifctx->replylen, TAG_DHCP_SERVERID);
556 if (p != NULL && gctx->tmptag.taglen == 4) {
557 memcpy(&ifctx->dhcpserver, p, 4);
558 ifctx->gotdhcpserver = 1;
559 } else
560 ifctx->gotdhcpserver = 0;
561 return 1;
562 }
563
564 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
565 ifctx->replylen,
566 TAG_ROOT) != NULL);
567 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
568 ifctx->replylen,
569 TAG_ROUTERS) != NULL);
570 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
571 ifctx->replylen,
572 TAG_SUBNETMASK) != NULL);
573 return 1;
574 }
575
576 static int
577 bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
578 {
579 struct sockaddr_in *sin, dst;
580 struct uio auio;
581 struct sockopt sopt;
582 struct iovec aio;
583 int error, on, rcvflg, timo, len;
584 time_t atimo;
585 time_t rtimo;
586 struct timeval tv;
587 struct bootpc_ifcontext *ifctx;
588 int outstanding;
589 int gotrootpath;
590 int retry;
591 const char *s;
592
593 tv.tv_sec = 1;
594 tv.tv_usec = 0;
595 bzero(&sopt, sizeof(sopt));
596 sopt.sopt_dir = SOPT_SET;
597 sopt.sopt_level = SOL_SOCKET;
598 sopt.sopt_name = SO_RCVTIMEO;
599 sopt.sopt_val = &tv;
600 sopt.sopt_valsize = sizeof tv;
601
602 error = sosetopt(bootp_so, &sopt);
603 if (error != 0)
604 goto out;
605
606 /*
607 * Enable broadcast.
608 */
609 on = 1;
610 sopt.sopt_name = SO_BROADCAST;
611 sopt.sopt_val = &on;
612 sopt.sopt_valsize = sizeof on;
613
614 error = sosetopt(bootp_so, &sopt);
615 if (error != 0)
616 goto out;
617
618 /*
619 * Disable routing.
620 */
621
622 on = 1;
623 sopt.sopt_name = SO_DONTROUTE;
624 sopt.sopt_val = &on;
625 sopt.sopt_valsize = sizeof on;
626
627 error = sosetopt(bootp_so, &sopt);
628 if (error != 0)
629 goto out;
630
631 /*
632 * Bind the local endpoint to a bootp client port.
633 */
634 sin = &dst;
635 clear_sinaddr(sin);
636 sin->sin_port = htons(IPPORT_BOOTPC);
637 error = sobind(bootp_so, (struct sockaddr *)sin, td);
638 if (error != 0) {
639 printf("bind failed\n");
640 goto out;
641 }
642
643 /*
644 * Setup socket address for the server.
645 */
646 sin = &dst;
647 clear_sinaddr(sin);
648 sin->sin_addr.s_addr = INADDR_BROADCAST;
649 sin->sin_port = htons(IPPORT_BOOTPS);
650
651 /*
652 * Send it, repeatedly, until a reply is received,
653 * but delay each re-send by an increasing amount.
654 * If the delay hits the maximum, start complaining.
655 */
656 timo = 0;
657 rtimo = 0;
658 for (;;) {
659
660 outstanding = 0;
661 gotrootpath = 0;
662
663 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
664 if (bootpc_ifctx_isresolved(ifctx) != 0 &&
665 bootpc_tag(&gctx->tmptag, &ifctx->reply,
666 ifctx->replylen,
667 TAG_ROOT) != NULL)
668 gotrootpath = 1;
669 }
670
671 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
672 struct in_aliasreq *ifra = &ifctx->iareq;
673 sin = (struct sockaddr_in *)&ifra->ifra_mask;
674
675 ifctx->outstanding = 0;
676 if (bootpc_ifctx_isresolved(ifctx) != 0 &&
677 gotrootpath != 0) {
678 continue;
679 }
680 if (bootpc_ifctx_isfailed(ifctx) != 0)
681 continue;
682
683 outstanding++;
684 ifctx->outstanding = 1;
685
686 /* Proceed to next step in DHCP negotiation */
687 if ((ifctx->state == IF_DHCP_OFFERED &&
688 ifctx->dhcpquerytype != DHCP_REQUEST) ||
689 (ifctx->state == IF_DHCP_UNRESOLVED &&
690 ifctx->dhcpquerytype != DHCP_DISCOVER) ||
691 (ifctx->state == IF_BOOTP_UNRESOLVED &&
692 ifctx->dhcpquerytype != DHCP_NOMSG)) {
693 ifctx->sentmsg = 0;
694 bootpc_compose_query(ifctx, td);
695 }
696
697 /* Send BOOTP request (or re-send). */
698
699 if (ifctx->sentmsg == 0) {
700 switch(ifctx->dhcpquerytype) {
701 case DHCP_DISCOVER:
702 s = "DHCP Discover";
703 break;
704 case DHCP_REQUEST:
705 s = "DHCP Request";
706 break;
707 case DHCP_NOMSG:
708 default:
709 s = "BOOTP Query";
710 break;
711 }
712 printf("Sending %s packet from "
713 "interface %s (%*D)\n",
714 s,
715 ifctx->ireq.ifr_name,
716 ifctx->sdl->sdl_alen,
717 (unsigned char *) LLADDR(ifctx->sdl),
718 ":");
719 ifctx->sentmsg = 1;
720 }
721
722 aio.iov_base = (caddr_t) &ifctx->call;
723 aio.iov_len = sizeof(ifctx->call);
724
725 auio.uio_iov = &aio;
726 auio.uio_iovcnt = 1;
727 auio.uio_segflg = UIO_SYSSPACE;
728 auio.uio_rw = UIO_WRITE;
729 auio.uio_offset = 0;
730 auio.uio_resid = sizeof(ifctx->call);
731 auio.uio_td = td;
732
733 /* Set netmask to 0.0.0.0 */
734 clear_sinaddr(sin);
735 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra,
736 td);
737 if (error != 0)
738 panic("%s: SIOCAIFADDR, error=%d", __func__,
739 error);
740
741 error = sosend(bootp_so, (struct sockaddr *) &dst,
742 &auio, NULL, NULL, 0, td);
743 if (error != 0)
744 printf("%s: sosend: %d state %08x\n", __func__,
745 error, (int )bootp_so->so_state);
746
747 /* Set netmask to 255.0.0.0 */
748 sin->sin_addr.s_addr = htonl(IN_CLASSA_NET);
749 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra,
750 td);
751 if (error != 0)
752 panic("%s: SIOCAIFADDR, error=%d", __func__,
753 error);
754 }
755
756 if (outstanding == 0 &&
757 (rtimo == 0 || time_second >= rtimo)) {
758 error = 0;
759 goto out;
760 }
761
762 /* Determine new timeout. */
763 if (timo < MAX_RESEND_DELAY)
764 timo++;
765 else {
766 printf("DHCP/BOOTP timeout for server ");
767 print_sin_addr(&dst);
768 printf("\n");
769 }
770
771 /*
772 * Wait for up to timo seconds for a reply.
773 * The socket receive timeout was set to 1 second.
774 */
775 atimo = timo + time_second;
776 while (time_second < atimo) {
777 aio.iov_base = (caddr_t) &gctx->reply;
778 aio.iov_len = sizeof(gctx->reply);
779
780 auio.uio_iov = &aio;
781 auio.uio_iovcnt = 1;
782 auio.uio_segflg = UIO_SYSSPACE;
783 auio.uio_rw = UIO_READ;
784 auio.uio_offset = 0;
785 auio.uio_resid = sizeof(gctx->reply);
786 auio.uio_td = td;
787
788 rcvflg = 0;
789 error = soreceive(bootp_so, NULL, &auio,
790 NULL, NULL, &rcvflg);
791 gctx->secs = time_second - gctx->starttime;
792 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
793 if (bootpc_ifctx_isresolved(ifctx) != 0 ||
794 bootpc_ifctx_isfailed(ifctx) != 0)
795 continue;
796
797 ifctx->call.secs = htons(gctx->secs);
798 }
799 if (error == EWOULDBLOCK)
800 continue;
801 if (error != 0)
802 goto out;
803 len = sizeof(gctx->reply) - auio.uio_resid;
804
805 /* Do we have the required number of bytes ? */
806 if (len < BOOTP_MIN_LEN)
807 continue;
808 gctx->replylen = len;
809
810 /* Is it a reply? */
811 if (gctx->reply.op != BOOTP_REPLY)
812 continue;
813
814 /* Is this an answer to our query */
815 STAILQ_FOREACH(ifctx, &gctx->interfaces, next) {
816 if (gctx->reply.xid != ifctx->call.xid)
817 continue;
818
819 /* Same HW address size ? */
820 if (gctx->reply.hlen != ifctx->call.hlen)
821 continue;
822
823 /* Correct HW address ? */
824 if (bcmp(gctx->reply.chaddr,
825 ifctx->call.chaddr,
826 ifctx->call.hlen) != 0)
827 continue;
828
829 break;
830 }
831
832 if (ifctx != NULL) {
833 s = bootpc_tag(&gctx->tmptag,
834 &gctx->reply,
835 gctx->replylen,
836 TAG_DHCP_MSGTYPE);
837 if (s != NULL) {
838 switch (*s) {
839 case DHCP_OFFER:
840 s = "DHCP Offer";
841 break;
842 case DHCP_ACK:
843 s = "DHCP Ack";
844 break;
845 default:
846 s = "DHCP (unexpected)";
847 break;
848 }
849 } else
850 s = "BOOTP Reply";
851
852 printf("Received %s packet"
853 " on %s from ",
854 s,
855 ifctx->ireq.ifr_name);
856 print_in_addr(gctx->reply.siaddr);
857 if (gctx->reply.giaddr.s_addr !=
858 htonl(INADDR_ANY)) {
859 printf(" via ");
860 print_in_addr(gctx->reply.giaddr);
861 }
862 if (bootpc_received(gctx, ifctx) != 0) {
863 printf(" (accepted)");
864 if (ifctx->outstanding) {
865 ifctx->outstanding = 0;
866 outstanding--;
867 }
868 /* Network settle delay */
869 if (outstanding == 0)
870 atimo = time_second +
871 BOOTP_SETTLE_DELAY;
872 } else
873 printf(" (ignored)");
874 if (ifctx->gotrootpath ||
875 gctx->any_root_overrides) {
876 gotrootpath = 1;
877 rtimo = time_second +
878 BOOTP_SETTLE_DELAY;
879 if (ifctx->gotrootpath)
880 printf(" (got root path)");
881 }
882 printf("\n");
883 }
884 } /* while secs */
885 #ifdef BOOTP_TIMEOUT
886 if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0)
887 break;
888 #endif
889 /* Force a retry if halfway in DHCP negotiation */
890 retry = 0;
891 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
892 if (ifctx->state == IF_DHCP_OFFERED) {
893 if (ifctx->dhcpquerytype == DHCP_DISCOVER)
894 retry = 1;
895 else
896 ifctx->state = IF_DHCP_UNRESOLVED;
897 }
898
899 if (retry != 0)
900 continue;
901
902 if (gotrootpath != 0) {
903 gctx->gotrootpath = gotrootpath;
904 if (rtimo != 0 && time_second >= rtimo)
905 break;
906 }
907 } /* forever send/receive */
908
909 /*
910 * XXX: These are errors of varying seriousness being silently
911 * ignored
912 */
913
914 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
915 if (bootpc_ifctx_isresolved(ifctx) == 0) {
916 printf("%s timeout for interface %s\n",
917 ifctx->dhcpquerytype != DHCP_NOMSG ?
918 "DHCP" : "BOOTP",
919 ifctx->ireq.ifr_name);
920 }
921
922 if (gctx->gotrootpath != 0) {
923 #if 0
924 printf("Got a root path, ignoring remaining timeout\n");
925 #endif
926 error = 0;
927 goto out;
928 }
929 #ifndef BOOTP_NFSROOT
930 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
931 if (bootpc_ifctx_isresolved(ifctx) != 0) {
932 error = 0;
933 goto out;
934 }
935 #endif
936 error = ETIMEDOUT;
937
938 out:
939 return (error);
940 }
941
942 static void
943 bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx, struct thread *td)
944 {
945 struct ifreq *ifr;
946 struct in_aliasreq *ifra;
947 struct sockaddr_in *sin;
948 int error;
949
950 ifr = &ifctx->ireq;
951 ifra = &ifctx->iareq;
952
953 /*
954 * Bring up the interface.
955 *
956 * Get the old interface flags and or IFF_UP into them; if
957 * IFF_UP set blindly, interface selection can be clobbered.
958 */
959 error = ifioctl(bootp_so, SIOCGIFFLAGS, (caddr_t)ifr, td);
960 if (error != 0)
961 panic("%s: SIOCGIFFLAGS, error=%d", __func__, error);
962 ifr->ifr_flags |= IFF_UP;
963 error = ifioctl(bootp_so, SIOCSIFFLAGS, (caddr_t)ifr, td);
964 if (error != 0)
965 panic("%s: SIOCSIFFLAGS, error=%d", __func__, error);
966
967 /*
968 * Do enough of ifconfig(8) so that the chosen interface
969 * can talk to the servers. Set address to 0.0.0.0/8 and
970 * broadcast address to local broadcast.
971 */
972 sin = (struct sockaddr_in *)&ifra->ifra_addr;
973 clear_sinaddr(sin);
974 sin = (struct sockaddr_in *)&ifra->ifra_mask;
975 clear_sinaddr(sin);
976 sin->sin_addr.s_addr = htonl(IN_CLASSA_NET);
977 sin = (struct sockaddr_in *)&ifra->ifra_broadaddr;
978 clear_sinaddr(sin);
979 sin->sin_addr.s_addr = htonl(INADDR_BROADCAST);
980 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td);
981 if (error != 0)
982 panic("%s: SIOCAIFADDR, error=%d", __func__, error);
983 }
984
985 static void
986 bootpc_shutdown_interface(struct bootpc_ifcontext *ifctx, struct thread *td)
987 {
988 struct ifreq *ifr;
989 struct sockaddr_in *sin;
990 int error;
991
992 ifr = &ifctx->ireq;
993
994 printf("Shutdown interface %s\n", ifctx->ireq.ifr_name);
995 error = ifioctl(bootp_so, SIOCGIFFLAGS, (caddr_t)ifr, td);
996 if (error != 0)
997 panic("%s: SIOCGIFFLAGS, error=%d", __func__, error);
998 ifr->ifr_flags &= ~IFF_UP;
999 error = ifioctl(bootp_so, SIOCSIFFLAGS, (caddr_t)ifr, td);
1000 if (error != 0)
1001 panic("%s: SIOCSIFFLAGS, error=%d", __func__, error);
1002
1003 sin = (struct sockaddr_in *) &ifr->ifr_addr;
1004 clear_sinaddr(sin);
1005 error = ifioctl(bootp_so, SIOCDIFADDR, (caddr_t) ifr, td);
1006 if (error != 0)
1007 panic("%s: SIOCDIFADDR, error=%d", __func__, error);
1008 }
1009
1010 static void
1011 bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
1012 struct bootpc_globalcontext *gctx, struct thread *td)
1013 {
1014 int error;
1015 struct sockaddr_in *sin;
1016 struct ifreq *ifr;
1017 struct in_aliasreq *ifra;
1018 struct sockaddr_in *myaddr;
1019 struct sockaddr_in *netmask;
1020
1021 ifr = &ifctx->ireq;
1022 ifra = &ifctx->iareq;
1023 myaddr = &ifctx->myaddr;
1024 netmask = &ifctx->netmask;
1025
1026 if (bootpc_ifctx_isresolved(ifctx) == 0) {
1027 /* Shutdown interfaces where BOOTP failed */
1028 bootpc_shutdown_interface(ifctx, td);
1029 return;
1030 }
1031
1032 printf("Adjusted interface %s", ifctx->ireq.ifr_name);
1033
1034 /* Do BOOTP interface options */
1035 if (ifctx->mtu != 0) {
1036 printf(" (MTU=%d%s)", ifctx->mtu,
1037 (ifctx->mtu > 1514) ? "/JUMBO" : "");
1038 ifr->ifr_mtu = ifctx->mtu;
1039 error = ifioctl(bootp_so, SIOCSIFMTU, (caddr_t) ifr, td);
1040 if (error != 0)
1041 panic("%s: SIOCSIFMTU, error=%d", __func__, error);
1042 }
1043 printf("\n");
1044
1045 /*
1046 * Do enough of ifconfig(8) so that the chosen interface
1047 * can talk to the servers. (just set the address)
1048 */
1049 sin = (struct sockaddr_in *) &ifr->ifr_addr;
1050 clear_sinaddr(sin);
1051 error = ifioctl(bootp_so, SIOCDIFADDR, (caddr_t) ifr, td);
1052 if (error != 0)
1053 panic("%s: SIOCDIFADDR, error=%d", __func__, error);
1054
1055 bcopy(myaddr, &ifra->ifra_addr, sizeof(*myaddr));
1056 bcopy(netmask, &ifra->ifra_mask, sizeof(*netmask));
1057 clear_sinaddr(&ifra->ifra_broadaddr);
1058 ifra->ifra_broadaddr.sin_addr.s_addr = myaddr->sin_addr.s_addr |
1059 ~netmask->sin_addr.s_addr;
1060
1061 error = ifioctl(bootp_so, SIOCAIFADDR, (caddr_t)ifra, td);
1062 if (error != 0)
1063 panic("%s: SIOCAIFADDR, error=%d", __func__, error);
1064 }
1065
1066 static void
1067 bootpc_add_default_route(struct bootpc_ifcontext *ifctx)
1068 {
1069 int error;
1070 struct sockaddr_in defdst;
1071 struct sockaddr_in defmask;
1072
1073 if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY))
1074 return;
1075
1076 clear_sinaddr(&defdst);
1077 clear_sinaddr(&defmask);
1078
1079 error = rtrequest_fib(RTM_ADD, (struct sockaddr *)&defdst,
1080 (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask,
1081 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
1082 if (error != 0) {
1083 printf("%s: RTM_ADD, error=%d\n", __func__, error);
1084 }
1085 }
1086
1087 static void
1088 bootpc_remove_default_route(struct bootpc_ifcontext *ifctx)
1089 {
1090 int error;
1091 struct sockaddr_in defdst;
1092 struct sockaddr_in defmask;
1093
1094 if (ifctx->gw.sin_addr.s_addr == htonl(INADDR_ANY))
1095 return;
1096
1097 clear_sinaddr(&defdst);
1098 clear_sinaddr(&defmask);
1099
1100 error = rtrequest_fib(RTM_DELETE, (struct sockaddr *)&defdst,
1101 (struct sockaddr *) &ifctx->gw, (struct sockaddr *)&defmask,
1102 (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, RT_DEFAULT_FIB);
1103 if (error != 0) {
1104 printf("%s: RTM_DELETE, error=%d\n", __func__, error);
1105 }
1106 }
1107
1108 static int
1109 setfs(struct sockaddr_in *addr, char *path, char *p,
1110 const struct in_addr *siaddr)
1111 {
1112
1113 if (getip(&p, &addr->sin_addr) == 0) {
1114 if (siaddr != NULL && *p == '/')
1115 bcopy(siaddr, &addr->sin_addr, sizeof(struct in_addr));
1116 else
1117 return 0;
1118 } else {
1119 if (*p != ':')
1120 return 0;
1121 p++;
1122 }
1123
1124 addr->sin_len = sizeof(struct sockaddr_in);
1125 addr->sin_family = AF_INET;
1126
1127 strlcpy(path, p, MNAMELEN);
1128 return 1;
1129 }
1130
1131 static int
1132 getip(char **ptr, struct in_addr *addr)
1133 {
1134 char *p;
1135 unsigned int ip;
1136 int val;
1137
1138 p = *ptr;
1139 ip = 0;
1140 if (((val = getdec(&p)) < 0) || (val > 255))
1141 return 0;
1142 ip = val << 24;
1143 if (*p != '.')
1144 return 0;
1145 p++;
1146 if (((val = getdec(&p)) < 0) || (val > 255))
1147 return 0;
1148 ip |= (val << 16);
1149 if (*p != '.')
1150 return 0;
1151 p++;
1152 if (((val = getdec(&p)) < 0) || (val > 255))
1153 return 0;
1154 ip |= (val << 8);
1155 if (*p != '.')
1156 return 0;
1157 p++;
1158 if (((val = getdec(&p)) < 0) || (val > 255))
1159 return 0;
1160 ip |= val;
1161
1162 addr->s_addr = htonl(ip);
1163 *ptr = p;
1164 return 1;
1165 }
1166
1167 static int
1168 getdec(char **ptr)
1169 {
1170 char *p;
1171 int ret;
1172
1173 p = *ptr;
1174 ret = 0;
1175 if ((*p < '') || (*p > '9'))
1176 return -1;
1177 while ((*p >= '') && (*p <= '9')) {
1178 ret = ret * 10 + (*p - '');
1179 p++;
1180 }
1181 *ptr = p;
1182 return ret;
1183 }
1184
1185 static void
1186 mountopts(struct nfs_args *args, char *p)
1187 {
1188 args->version = NFS_ARGSVERSION;
1189 args->rsize = BOOTP_BLOCKSIZE;
1190 args->wsize = BOOTP_BLOCKSIZE;
1191 args->flags = NFSMNT_RSIZE | NFSMNT_WSIZE | NFSMNT_RESVPORT;
1192 args->sotype = SOCK_DGRAM;
1193 if (p != NULL)
1194 nfs_parse_options(p, args);
1195 }
1196
1197 static int
1198 xdr_opaque_decode(struct mbuf **mptr, u_char *buf, int len)
1199 {
1200 struct mbuf *m;
1201 int alignedlen;
1202
1203 m = *mptr;
1204 alignedlen = ( len + 3 ) & ~3;
1205
1206 if (m->m_len < alignedlen) {
1207 m = m_pullup(m, alignedlen);
1208 if (m == NULL) {
1209 *mptr = NULL;
1210 return EBADRPC;
1211 }
1212 }
1213 bcopy(mtod(m, u_char *), buf, len);
1214 m_adj(m, alignedlen);
1215 *mptr = m;
1216 return 0;
1217 }
1218
1219 static int
1220 xdr_int_decode(struct mbuf **mptr, int *iptr)
1221 {
1222 u_int32_t i;
1223
1224 if (xdr_opaque_decode(mptr, (u_char *) &i, sizeof(u_int32_t)) != 0)
1225 return EBADRPC;
1226 *iptr = fxdr_unsigned(u_int32_t, i);
1227 return 0;
1228 }
1229
1230 static void
1231 print_sin_addr(struct sockaddr_in *sin)
1232 {
1233
1234 print_in_addr(sin->sin_addr);
1235 }
1236
1237 static void
1238 print_in_addr(struct in_addr addr)
1239 {
1240 unsigned int ip;
1241
1242 ip = ntohl(addr.s_addr);
1243 printf("%d.%d.%d.%d",
1244 ip >> 24, (ip >> 16) & 255, (ip >> 8) & 255, ip & 255);
1245 }
1246
1247 static void
1248 bootpc_compose_query(struct bootpc_ifcontext *ifctx, struct thread *td)
1249 {
1250 unsigned char *vendp;
1251 unsigned char vendor_client[64];
1252 uint32_t leasetime;
1253 uint8_t vendor_client_len;
1254
1255 ifctx->gotrootpath = 0;
1256
1257 bzero((caddr_t) &ifctx->call, sizeof(ifctx->call));
1258
1259 /* bootpc part */
1260 ifctx->call.op = BOOTP_REQUEST; /* BOOTREQUEST */
1261 ifctx->call.htype = 1; /* 10mb ethernet */
1262 ifctx->call.hlen = ifctx->sdl->sdl_alen;/* Hardware address length */
1263 ifctx->call.hops = 0;
1264 if (bootpc_ifctx_isunresolved(ifctx) != 0)
1265 ifctx->xid++;
1266 ifctx->call.xid = txdr_unsigned(ifctx->xid);
1267 bcopy(LLADDR(ifctx->sdl), &ifctx->call.chaddr, ifctx->sdl->sdl_alen);
1268
1269 vendp = ifctx->call.vend;
1270 *vendp++ = 99; /* RFC1048 cookie */
1271 *vendp++ = 130;
1272 *vendp++ = 83;
1273 *vendp++ = 99;
1274 *vendp++ = TAG_MAXMSGSIZE;
1275 *vendp++ = 2;
1276 *vendp++ = (sizeof(struct bootp_packet) >> 8) & 255;
1277 *vendp++ = sizeof(struct bootp_packet) & 255;
1278
1279 snprintf(vendor_client, sizeof(vendor_client), "%s:%s:%s",
1280 ostype, MACHINE, osrelease);
1281 vendor_client_len = strlen(vendor_client);
1282 *vendp++ = TAG_VENDOR_INDENTIFIER;
1283 *vendp++ = vendor_client_len;
1284 memcpy(vendp, vendor_client, vendor_client_len);
1285 vendp += vendor_client_len;
1286 ifctx->dhcpquerytype = DHCP_NOMSG;
1287 switch (ifctx->state) {
1288 case IF_DHCP_UNRESOLVED:
1289 *vendp++ = TAG_DHCP_MSGTYPE;
1290 *vendp++ = 1;
1291 *vendp++ = DHCP_DISCOVER;
1292 ifctx->dhcpquerytype = DHCP_DISCOVER;
1293 ifctx->gotdhcpserver = 0;
1294 break;
1295 case IF_DHCP_OFFERED:
1296 *vendp++ = TAG_DHCP_MSGTYPE;
1297 *vendp++ = 1;
1298 *vendp++ = DHCP_REQUEST;
1299 ifctx->dhcpquerytype = DHCP_REQUEST;
1300 *vendp++ = TAG_DHCP_REQ_ADDR;
1301 *vendp++ = 4;
1302 memcpy(vendp, &ifctx->reply.yiaddr, 4);
1303 vendp += 4;
1304 if (ifctx->gotdhcpserver != 0) {
1305 *vendp++ = TAG_DHCP_SERVERID;
1306 *vendp++ = 4;
1307 memcpy(vendp, &ifctx->dhcpserver, 4);
1308 vendp += 4;
1309 }
1310 *vendp++ = TAG_DHCP_LEASETIME;
1311 *vendp++ = 4;
1312 leasetime = htonl(300);
1313 memcpy(vendp, &leasetime, 4);
1314 vendp += 4;
1315 break;
1316 default:
1317 break;
1318 }
1319 *vendp = TAG_END;
1320
1321 ifctx->call.secs = 0;
1322 ifctx->call.flags = htons(0x8000); /* We need a broadcast answer */
1323 }
1324
1325 static int
1326 bootpc_hascookie(struct bootp_packet *bp)
1327 {
1328
1329 return (bp->vend[0] == 99 && bp->vend[1] == 130 &&
1330 bp->vend[2] == 83 && bp->vend[3] == 99);
1331 }
1332
1333 static void
1334 bootpc_tag_helper(struct bootpc_tagcontext *tctx,
1335 unsigned char *start, int len, int tag)
1336 {
1337 unsigned char *j;
1338 unsigned char *ej;
1339 unsigned char code;
1340
1341 if (tctx->badtag != 0 || tctx->badopt != 0)
1342 return;
1343
1344 j = start;
1345 ej = j + len;
1346
1347 while (j < ej) {
1348 code = *j++;
1349 if (code == TAG_PAD)
1350 continue;
1351 if (code == TAG_END)
1352 return;
1353 if (j >= ej || j + *j + 1 > ej) {
1354 tctx->badopt = 1;
1355 return;
1356 }
1357 len = *j++;
1358 if (code == tag) {
1359 if (tctx->taglen + len > TAG_MAXLEN) {
1360 tctx->badtag = 1;
1361 return;
1362 }
1363 tctx->foundopt = 1;
1364 if (len > 0)
1365 memcpy(tctx->buf + tctx->taglen,
1366 j, len);
1367 tctx->taglen += len;
1368 }
1369 if (code == TAG_OVERLOAD)
1370 tctx->overload = *j;
1371
1372 j += len;
1373 }
1374 }
1375
1376 static unsigned char *
1377 bootpc_tag(struct bootpc_tagcontext *tctx,
1378 struct bootp_packet *bp, int len, int tag)
1379 {
1380 tctx->overload = 0;
1381 tctx->badopt = 0;
1382 tctx->badtag = 0;
1383 tctx->foundopt = 0;
1384 tctx->taglen = 0;
1385
1386 if (bootpc_hascookie(bp) == 0)
1387 return NULL;
1388
1389 bootpc_tag_helper(tctx, &bp->vend[4],
1390 (unsigned char *) bp + len - &bp->vend[4], tag);
1391
1392 if ((tctx->overload & OVERLOAD_FILE) != 0)
1393 bootpc_tag_helper(tctx,
1394 (unsigned char *) bp->file,
1395 sizeof(bp->file),
1396 tag);
1397 if ((tctx->overload & OVERLOAD_SNAME) != 0)
1398 bootpc_tag_helper(tctx,
1399 (unsigned char *) bp->sname,
1400 sizeof(bp->sname),
1401 tag);
1402
1403 if (tctx->badopt != 0 || tctx->badtag != 0 || tctx->foundopt == 0)
1404 return NULL;
1405 tctx->buf[tctx->taglen] = '\0';
1406 return tctx->buf;
1407 }
1408
1409 static void
1410 bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx,
1411 struct bootpc_globalcontext *gctx)
1412 {
1413 char *p, *s;
1414 unsigned int ip;
1415
1416 ifctx->gotgw = 0;
1417 ifctx->gotnetmask = 0;
1418
1419 clear_sinaddr(&ifctx->myaddr);
1420 clear_sinaddr(&ifctx->netmask);
1421 clear_sinaddr(&ifctx->gw);
1422
1423 ifctx->myaddr.sin_addr = ifctx->reply.yiaddr;
1424
1425 ip = ntohl(ifctx->myaddr.sin_addr.s_addr);
1426
1427 printf("%s at ", ifctx->ireq.ifr_name);
1428 print_sin_addr(&ifctx->myaddr);
1429 printf(" server ");
1430 print_in_addr(ifctx->reply.siaddr);
1431
1432 ifctx->gw.sin_addr = ifctx->reply.giaddr;
1433 if (ifctx->reply.giaddr.s_addr != htonl(INADDR_ANY)) {
1434 printf(" via gateway ");
1435 print_in_addr(ifctx->reply.giaddr);
1436 }
1437
1438 /* This call used for the side effect (overload flag) */
1439 (void) bootpc_tag(&gctx->tmptag,
1440 &ifctx->reply, ifctx->replylen, TAG_END);
1441
1442 if ((gctx->tmptag.overload & OVERLOAD_SNAME) == 0)
1443 if (ifctx->reply.sname[0] != '\0')
1444 printf(" server name %s", ifctx->reply.sname);
1445 if ((gctx->tmptag.overload & OVERLOAD_FILE) == 0)
1446 if (ifctx->reply.file[0] != '\0')
1447 printf(" boot file %s", ifctx->reply.file);
1448
1449 printf("\n");
1450
1451 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1452 TAG_SUBNETMASK);
1453 if (p != NULL) {
1454 if (gctx->tag.taglen != 4)
1455 panic("bootpc: subnet mask len is %d",
1456 gctx->tag.taglen);
1457 bcopy(p, &ifctx->netmask.sin_addr, 4);
1458 ifctx->gotnetmask = 1;
1459 printf("subnet mask ");
1460 print_sin_addr(&ifctx->netmask);
1461 printf(" ");
1462 }
1463
1464 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1465 TAG_ROUTERS);
1466 if (p != NULL) {
1467 /* Routers */
1468 if (gctx->tag.taglen % 4)
1469 panic("bootpc: Router Len is %d", gctx->tag.taglen);
1470 if (gctx->tag.taglen > 0) {
1471 bcopy(p, &ifctx->gw.sin_addr, 4);
1472 printf("router ");
1473 print_sin_addr(&ifctx->gw);
1474 printf(" ");
1475 ifctx->gotgw = 1;
1476 gctx->gotgw = 1;
1477 }
1478 }
1479
1480 /*
1481 * Choose a root filesystem. If a value is forced in the environment
1482 * and it contains "nfs:", use it unconditionally. Otherwise, if the
1483 * kernel is compiled with the ROOTDEVNAME option, then use it if:
1484 * - The server doesn't provide a pathname.
1485 * - The boothowto flags include RB_DFLTROOT (user said to override
1486 * the server value).
1487 */
1488 p = NULL;
1489 if ((s = getenv("vfs.root.mountfrom")) != NULL) {
1490 if ((p = strstr(s, "nfs:")) != NULL)
1491 p = strdup(p + 4, M_TEMP);
1492 freeenv(s);
1493 }
1494 if (p == NULL) {
1495 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1496 TAG_ROOT);
1497 if (p != NULL)
1498 ifctx->gotrootpath = 1;
1499 }
1500 #ifdef ROOTDEVNAME
1501 if ((p == NULL || (boothowto & RB_DFLTROOT) != 0) &&
1502 (p = strstr(ROOTDEVNAME, "nfs:")) != NULL) {
1503 p += 4;
1504 }
1505 #endif
1506 if (p != NULL) {
1507 if (gctx->setrootfs != NULL) {
1508 printf("rootfs %s (ignored) ", p);
1509 } else if (setfs(&nd->root_saddr,
1510 nd->root_hostnam, p, &ifctx->reply.siaddr)) {
1511 if (*p == '/') {
1512 printf("root_server ");
1513 print_sin_addr(&nd->root_saddr);
1514 printf(" ");
1515 }
1516 printf("rootfs %s ", p);
1517 gctx->gotrootpath = 1;
1518 gctx->setrootfs = ifctx;
1519
1520 p = bootpc_tag(&gctx->tag, &ifctx->reply,
1521 ifctx->replylen,
1522 TAG_ROOTOPTS);
1523 if (p != NULL) {
1524 mountopts(&nd->root_args, p);
1525 printf("rootopts %s ", p);
1526 }
1527 } else
1528 panic("Failed to set rootfs to %s", p);
1529 }
1530
1531 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1532 TAG_HOSTNAME);
1533 if (p != NULL) {
1534 if (gctx->tag.taglen >= MAXHOSTNAMELEN)
1535 panic("bootpc: hostname >= %d bytes",
1536 MAXHOSTNAMELEN);
1537 if (gctx->sethostname != NULL) {
1538 printf("hostname %s (ignored) ", p);
1539 } else {
1540 strcpy(nd->my_hostnam, p);
1541 mtx_lock(&prison0.pr_mtx);
1542 strcpy(prison0.pr_hostname, p);
1543 mtx_unlock(&prison0.pr_mtx);
1544 printf("hostname %s ", p);
1545 gctx->sethostname = ifctx;
1546 }
1547 }
1548 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1549 TAG_COOKIE);
1550 if (p != NULL) { /* store in a sysctl variable */
1551 int i, l = sizeof(bootp_cookie) - 1;
1552 for (i = 0; i < l && p[i] != '\0'; i++)
1553 bootp_cookie[i] = p[i];
1554 p[i] = '\0';
1555 }
1556
1557 p = bootpc_tag(&gctx->tag, &ifctx->reply, ifctx->replylen,
1558 TAG_INTF_MTU);
1559 if (p != NULL) {
1560 ifctx->mtu = be16dec(p);
1561 }
1562
1563 printf("\n");
1564
1565 if (ifctx->gotnetmask == 0) {
1566 if (IN_CLASSA(ntohl(ifctx->myaddr.sin_addr.s_addr)))
1567 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSA_NET);
1568 else if (IN_CLASSB(ntohl(ifctx->myaddr.sin_addr.s_addr)))
1569 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSB_NET);
1570 else
1571 ifctx->netmask.sin_addr.s_addr = htonl(IN_CLASSC_NET);
1572 }
1573 }
1574
1575 void
1576 bootpc_init(void)
1577 {
1578 struct bootpc_ifcontext *ifctx; /* Interface BOOTP contexts */
1579 struct bootpc_globalcontext *gctx; /* Global BOOTP context */
1580 struct ifnet *ifp;
1581 struct sockaddr_dl *sdl;
1582 struct ifaddr *ifa;
1583 int error;
1584 #ifndef BOOTP_WIRED_TO
1585 int ifcnt;
1586 #endif
1587 struct nfsv3_diskless *nd;
1588 struct thread *td;
1589 int timeout;
1590 int delay;
1591
1592 timeout = BOOTP_IFACE_WAIT_TIMEOUT * hz;
1593 delay = hz / 10;
1594
1595 nd = &nfsv3_diskless;
1596 td = curthread;
1597
1598 /*
1599 * If already filled in, don't touch it here
1600 */
1601 if (nfs_diskless_valid != 0)
1602 return;
1603
1604 gctx = malloc(sizeof(*gctx), M_TEMP, M_WAITOK | M_ZERO);
1605 STAILQ_INIT(&gctx->interfaces);
1606 gctx->xid = ~0xFFFF;
1607 gctx->starttime = time_second;
1608
1609 /*
1610 * If ROOTDEVNAME is defined or vfs.root.mountfrom is set then we have
1611 * root-path overrides that can potentially let us boot even if we don't
1612 * get a root path from the server, so we can treat that as a non-error.
1613 */
1614 #ifdef ROOTDEVNAME
1615 gctx->any_root_overrides = 1;
1616 #else
1617 gctx->any_root_overrides = testenv("vfs.root.mountfrom");
1618 #endif
1619
1620 /*
1621 * Find a network interface.
1622 */
1623 CURVNET_SET(TD_TO_VNET(td));
1624 #ifdef BOOTP_WIRED_TO
1625 printf("%s: wired to interface '%s'\n", __func__,
1626 __XSTRING(BOOTP_WIRED_TO));
1627 allocifctx(gctx);
1628 #else
1629 /*
1630 * Preallocate interface context storage, if another interface
1631 * attaches and wins the race, it won't be eligible for bootp.
1632 */
1633 ifcnt = 0;
1634 IFNET_RLOCK();
1635 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1636 if ((ifp->if_flags &
1637 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
1638 IFF_BROADCAST)
1639 continue;
1640 switch (ifp->if_alloctype) {
1641 case IFT_ETHER:
1642 case IFT_FDDI:
1643 case IFT_ISO88025:
1644 break;
1645 default:
1646 continue;
1647 }
1648 ifcnt++;
1649 }
1650 IFNET_RUNLOCK();
1651 if (ifcnt == 0)
1652 panic("%s: no eligible interfaces", __func__);
1653 for (; ifcnt > 0; ifcnt--)
1654 allocifctx(gctx);
1655 #endif
1656
1657 retry:
1658 ifctx = STAILQ_FIRST(&gctx->interfaces);
1659 IFNET_RLOCK();
1660 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1661 if (ifctx == NULL)
1662 break;
1663 #ifdef BOOTP_WIRED_TO
1664 if (strcmp(ifp->if_xname, __XSTRING(BOOTP_WIRED_TO)) != 0)
1665 continue;
1666 #else
1667 if ((ifp->if_flags &
1668 (IFF_LOOPBACK | IFF_POINTOPOINT | IFF_BROADCAST)) !=
1669 IFF_BROADCAST)
1670 continue;
1671 switch (ifp->if_alloctype) {
1672 case IFT_ETHER:
1673 case IFT_FDDI:
1674 case IFT_ISO88025:
1675 break;
1676 default:
1677 continue;
1678 }
1679 #endif
1680 strlcpy(ifctx->ireq.ifr_name, ifp->if_xname,
1681 sizeof(ifctx->ireq.ifr_name));
1682 ifctx->ifp = ifp;
1683
1684 /* Get HW address */
1685 sdl = NULL;
1686 TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
1687 if (ifa->ifa_addr->sa_family == AF_LINK) {
1688 sdl = (struct sockaddr_dl *)ifa->ifa_addr;
1689 if (sdl->sdl_type == IFT_ETHER)
1690 break;
1691 }
1692 if (sdl == NULL)
1693 panic("bootpc: Unable to find HW address for %s",
1694 ifctx->ireq.ifr_name);
1695 ifctx->sdl = sdl;
1696
1697 ifctx = STAILQ_NEXT(ifctx, next);
1698 }
1699 IFNET_RUNLOCK();
1700 CURVNET_RESTORE();
1701
1702 if (STAILQ_EMPTY(&gctx->interfaces) ||
1703 STAILQ_FIRST(&gctx->interfaces)->ifp == NULL) {
1704 if (timeout > 0) {
1705 pause("bootpc", delay);
1706 timeout -= delay;
1707 goto retry;
1708 }
1709 #ifdef BOOTP_WIRED_TO
1710 panic("%s: Could not find interface specified "
1711 "by BOOTP_WIRED_TO: "
1712 __XSTRING(BOOTP_WIRED_TO), __func__);
1713 #else
1714 panic("%s: no suitable interface", __func__);
1715 #endif
1716 }
1717
1718 error = socreate(AF_INET, &bootp_so, SOCK_DGRAM, 0, td->td_ucred, td);
1719 if (error != 0)
1720 panic("%s: socreate, error=%d", __func__, error);
1721
1722 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
1723 bootpc_fakeup_interface(ifctx, td);
1724
1725 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
1726 bootpc_compose_query(ifctx, td);
1727
1728 error = bootpc_call(gctx, td);
1729 if (error != 0) {
1730 printf("BOOTP call failed\n");
1731 }
1732
1733 mountopts(&nd->root_args, NULL);
1734
1735 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
1736 if (bootpc_ifctx_isresolved(ifctx) != 0)
1737 bootpc_decode_reply(nd, ifctx, gctx);
1738
1739 #ifdef BOOTP_NFSROOT
1740 if (gctx->gotrootpath == 0 && gctx->any_root_overrides == 0)
1741 panic("bootpc: No root path offered");
1742 #endif
1743
1744 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
1745 bootpc_adjust_interface(ifctx, gctx, td);
1746
1747 soclose(bootp_so);
1748
1749 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
1750 if (ifctx->gotrootpath != 0)
1751 break;
1752 if (ifctx == NULL) {
1753 STAILQ_FOREACH(ifctx, &gctx->interfaces, next)
1754 if (bootpc_ifctx_isresolved(ifctx) != 0)
1755 break;
1756 }
1757 if (ifctx == NULL)
1758 goto out;
1759
1760 if (gctx->gotrootpath != 0) {
1761
1762 setenv("boot.netif.name", ifctx->ifp->if_xname);
1763
1764 bootpc_add_default_route(ifctx);
1765 error = md_mount(&nd->root_saddr, nd->root_hostnam,
1766 nd->root_fh, &nd->root_fhsize,
1767 &nd->root_args, td);
1768 bootpc_remove_default_route(ifctx);
1769 if (error != 0) {
1770 if (gctx->any_root_overrides == 0)
1771 panic("nfs_boot: mount root, error=%d", error);
1772 else
1773 goto out;
1774 }
1775 rootdevnames[0] = "nfs:";
1776 #ifdef NFSCLIENT
1777 rootdevnames[1] = "oldnfs:";
1778 #endif
1779 nfs_diskless_valid = 3;
1780 }
1781
1782 strcpy(nd->myif.ifra_name, ifctx->ireq.ifr_name);
1783 bcopy(&ifctx->myaddr, &nd->myif.ifra_addr, sizeof(ifctx->myaddr));
1784 bcopy(&ifctx->myaddr, &nd->myif.ifra_broadaddr, sizeof(ifctx->myaddr));
1785 ((struct sockaddr_in *) &nd->myif.ifra_broadaddr)->sin_addr.s_addr =
1786 ifctx->myaddr.sin_addr.s_addr |
1787 ~ ifctx->netmask.sin_addr.s_addr;
1788 bcopy(&ifctx->netmask, &nd->myif.ifra_mask, sizeof(ifctx->netmask));
1789 bcopy(&ifctx->gw, &nd->mygateway, sizeof(ifctx->gw));
1790
1791 out:
1792 while((ifctx = STAILQ_FIRST(&gctx->interfaces)) != NULL) {
1793 STAILQ_REMOVE_HEAD(&gctx->interfaces, next);
1794 free(ifctx, M_TEMP);
1795 }
1796 free(gctx, M_TEMP);
1797 }
1798
1799 /*
1800 * RPC: mountd/mount
1801 * Given a server pathname, get an NFS file handle.
1802 * Also, sets sin->sin_port to the NFS service port.
1803 */
1804 static int
1805 md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep,
1806 struct nfs_args *args, struct thread *td)
1807 {
1808 struct mbuf *m;
1809 int error;
1810 int authunixok;
1811 int authcount;
1812 int authver;
1813
1814 #define RPCPROG_MNT 100005
1815 #define RPCMNT_VER1 1
1816 #define RPCMNT_VER3 3
1817 #define RPCMNT_MOUNT 1
1818 #define AUTH_SYS 1 /* unix style (uid, gids) */
1819 #define AUTH_UNIX AUTH_SYS
1820
1821 /* XXX honor v2/v3 flags in args->flags? */
1822 #ifdef BOOTP_NFSV3
1823 /* First try NFS v3 */
1824 /* Get port number for MOUNTD. */
1825 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1826 &mdsin->sin_port, td);
1827 if (error == 0) {
1828 m = xdr_string_encode(path, strlen(path));
1829
1830 /* Do RPC to mountd. */
1831 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER3,
1832 RPCMNT_MOUNT, &m, NULL, td);
1833 }
1834 if (error == 0) {
1835 args->flags |= NFSMNT_NFSV3;
1836 } else {
1837 #endif
1838 /* Fallback to NFS v2 */
1839
1840 /* Get port number for MOUNTD. */
1841 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1842 &mdsin->sin_port, td);
1843 if (error != 0)
1844 return error;
1845
1846 m = xdr_string_encode(path, strlen(path));
1847
1848 /* Do RPC to mountd. */
1849 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
1850 RPCMNT_MOUNT, &m, NULL, td);
1851 if (error != 0)
1852 return error; /* message already freed */
1853
1854 #ifdef BOOTP_NFSV3
1855 }
1856 #endif
1857
1858 if (xdr_int_decode(&m, &error) != 0 || error != 0)
1859 goto bad;
1860
1861 if ((args->flags & NFSMNT_NFSV3) != 0) {
1862 if (xdr_int_decode(&m, fhsizep) != 0 ||
1863 *fhsizep > NFSX_V3FHMAX ||
1864 *fhsizep <= 0)
1865 goto bad;
1866 } else
1867 *fhsizep = NFSX_V2FH;
1868
1869 if (xdr_opaque_decode(&m, fhp, *fhsizep) != 0)
1870 goto bad;
1871
1872 if (args->flags & NFSMNT_NFSV3) {
1873 if (xdr_int_decode(&m, &authcount) != 0)
1874 goto bad;
1875 authunixok = 0;
1876 if (authcount < 0 || authcount > 100)
1877 goto bad;
1878 while (authcount > 0) {
1879 if (xdr_int_decode(&m, &authver) != 0)
1880 goto bad;
1881 if (authver == AUTH_UNIX)
1882 authunixok = 1;
1883 authcount--;
1884 }
1885 if (authunixok == 0)
1886 goto bad;
1887 }
1888
1889 /* Set port number for NFS use. */
1890 error = krpc_portmap(mdsin, NFS_PROG,
1891 (args->flags &
1892 NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
1893 &mdsin->sin_port, td);
1894
1895 goto out;
1896
1897 bad:
1898 error = EBADRPC;
1899
1900 out:
1901 m_freem(m);
1902 return error;
1903 }
1904
1905 SYSINIT(bootp_rootconf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, bootpc_init, NULL);
Cache object: b6f1b0c0b4423192b1aec22e214bfc2c
|