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: src/sys/nfsclient/bootp_subr.c,v 1.74 2008/08/17 23:27:27 bz Exp $");
45
46 #include "opt_bootp.h"
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/sockio.h>
52 #include <sys/malloc.h>
53 #include <sys/mount.h>
54 #include <sys/mbuf.h>
55 #include <sys/proc.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/sysctl.h>
59 #include <sys/uio.h>
60 #include <sys/vimage.h>
61
62 #include <net/if.h>
63 #include <net/route.h>
64
65 #include <netinet/in.h>
66 #include <net/if_types.h>
67 #include <net/if_dl.h>
68
69 #include <rpc/rpcclnt.h>
70
71 #include <nfs/rpcv2.h>
72 #include <nfs/nfsproto.h>
73 #include <nfsclient/nfs.h>
74 #include <nfsclient/nfsdiskless.h>
75 #include <nfsclient/krpc.h>
76 #include <nfs/xdr_subs.h>
77
78
79 #define BOOTP_MIN_LEN 300 /* Minimum size of bootp udp packet */
80
81 #ifndef BOOTP_SETTLE_DELAY
82 #define BOOTP_SETTLE_DELAY 3
83 #endif
84
85 /*
86 * What is the longest we will wait before re-sending a request?
87 * Note this is also the frequency of "RPC timeout" messages.
88 * The re-send loop count sup linearly to this maximum, so the
89 * first complaint will happen after (1+2+3+4+5)=15 seconds.
90 */
91 #define MAX_RESEND_DELAY 5 /* seconds */
92
93 /* Definitions from RFC951 */
94 struct bootp_packet {
95 u_int8_t op;
96 u_int8_t htype;
97 u_int8_t hlen;
98 u_int8_t hops;
99 u_int32_t xid;
100 u_int16_t secs;
101 u_int16_t flags;
102 struct in_addr ciaddr;
103 struct in_addr yiaddr;
104 struct in_addr siaddr;
105 struct in_addr giaddr;
106 unsigned char chaddr[16];
107 char sname[64];
108 char file[128];
109 unsigned char vend[1222];
110 };
111
112 struct bootpc_ifcontext {
113 struct bootpc_ifcontext *next;
114 struct bootp_packet call;
115 struct bootp_packet reply;
116 int replylen;
117 int overload;
118 struct socket *so;
119 struct ifreq ireq;
120 struct ifnet *ifp;
121 struct sockaddr_dl *sdl;
122 struct sockaddr_in myaddr;
123 struct sockaddr_in netmask;
124 struct sockaddr_in gw;
125 struct sockaddr_in broadcast; /* Different for each interface */
126 int gotgw;
127 int gotnetmask;
128 int gotrootpath;
129 int outstanding;
130 int sentmsg;
131 u_int32_t xid;
132 enum {
133 IF_BOOTP_UNRESOLVED,
134 IF_BOOTP_RESOLVED,
135 IF_BOOTP_FAILED,
136 IF_DHCP_UNRESOLVED,
137 IF_DHCP_OFFERED,
138 IF_DHCP_RESOLVED,
139 IF_DHCP_FAILED,
140 } state;
141 int dhcpquerytype; /* dhcp type sent */
142 struct in_addr dhcpserver;
143 int gotdhcpserver;
144 };
145
146 #define TAG_MAXLEN 1024
147 struct bootpc_tagcontext {
148 char buf[TAG_MAXLEN + 1];
149 int overload;
150 int badopt;
151 int badtag;
152 int foundopt;
153 int taglen;
154 };
155
156 struct bootpc_globalcontext {
157 struct bootpc_ifcontext *interfaces;
158 struct bootpc_ifcontext *lastinterface;
159 u_int32_t xid;
160 int gotrootpath;
161 int gotgw;
162 int ifnum;
163 int secs;
164 int starttime;
165 struct bootp_packet reply;
166 int replylen;
167 struct bootpc_ifcontext *setrootfs;
168 struct bootpc_ifcontext *sethostname;
169 struct bootpc_tagcontext tmptag;
170 struct bootpc_tagcontext tag;
171 };
172
173 #define IPPORT_BOOTPC 68
174 #define IPPORT_BOOTPS 67
175
176 #define BOOTP_REQUEST 1
177 #define BOOTP_REPLY 2
178
179 /* Common tags */
180 #define TAG_PAD 0 /* Pad option, implicit length 1 */
181 #define TAG_SUBNETMASK 1 /* RFC 950 subnet mask */
182 #define TAG_ROUTERS 3 /* Routers (in order of preference) */
183 #define TAG_HOSTNAME 12 /* Client host name */
184 #define TAG_ROOT 17 /* Root path */
185
186 /* DHCP specific tags */
187 #define TAG_OVERLOAD 52 /* Option Overload */
188 #define TAG_MAXMSGSIZE 57 /* Maximum DHCP Message Size */
189
190 #define TAG_END 255 /* End Option (i.e. no more options) */
191
192 /* Overload values */
193 #define OVERLOAD_FILE 1
194 #define OVERLOAD_SNAME 2
195
196 /* Site specific tags: */
197 #define TAG_ROOTOPTS 130
198 #define TAG_COOKIE 134 /* ascii info for userland, via sysctl */
199
200 #define TAG_DHCP_MSGTYPE 53
201 #define TAG_DHCP_REQ_ADDR 50
202 #define TAG_DHCP_SERVERID 54
203 #define TAG_DHCP_LEASETIME 51
204
205 #define TAG_VENDOR_INDENTIFIER 60
206
207 #define DHCP_NOMSG 0
208 #define DHCP_DISCOVER 1
209 #define DHCP_OFFER 2
210 #define DHCP_REQUEST 3
211 #define DHCP_ACK 5
212
213 /* NFS read/write block size */
214 #ifndef BOOTP_BLOCKSIZE
215 #define BOOTP_BLOCKSIZE 8192
216 #endif
217
218 static char bootp_cookie[128];
219 SYSCTL_STRING(_kern, OID_AUTO, bootp_cookie, CTLFLAG_RD,
220 bootp_cookie, 0, "Cookie (T134) supplied by bootp server");
221
222 /* mountd RPC */
223 static int md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp,
224 int *fhsizep, struct nfs_args *args, struct thread *td);
225 static int setfs(struct sockaddr_in *addr, char *path, char *p,
226 const struct in_addr *siaddr);
227 static int getdec(char **ptr);
228 static int getip(char **ptr, struct in_addr *ip);
229 static void mountopts(struct nfs_args *args, char *p);
230 static int xdr_opaque_decode(struct mbuf **ptr, u_char *buf, int len);
231 static int xdr_int_decode(struct mbuf **ptr, int *iptr);
232 static void print_in_addr(struct in_addr addr);
233 static void print_sin_addr(struct sockaddr_in *addr);
234 static void clear_sinaddr(struct sockaddr_in *sin);
235 static void allocifctx(struct bootpc_globalcontext *gctx);
236 static void bootpc_compose_query(struct bootpc_ifcontext *ifctx,
237 struct bootpc_globalcontext *gctx, struct thread *td);
238 static unsigned char *bootpc_tag(struct bootpc_tagcontext *tctx,
239 struct bootp_packet *bp, int len, int tag);
240 static void bootpc_tag_helper(struct bootpc_tagcontext *tctx,
241 unsigned char *start, int len, int tag);
242
243 #ifdef BOOTP_DEBUG
244 void bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma);
245 void bootpboot_p_ma(struct sockaddr *ma);
246 void bootpboot_p_rtentry(struct rtentry *rt);
247 void bootpboot_p_tree(struct radix_node *rn);
248 void bootpboot_p_rtlist(void);
249 void bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa);
250 void bootpboot_p_iflist(void);
251 #endif
252
253 static int bootpc_call(struct bootpc_globalcontext *gctx,
254 struct thread *td);
255
256 static int bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
257 struct bootpc_globalcontext *gctx, struct thread *td);
258
259 static int bootpc_adjust_interface(struct bootpc_ifcontext *ifctx,
260 struct bootpc_globalcontext *gctx, struct thread *td);
261
262 static void bootpc_decode_reply(struct nfsv3_diskless *nd,
263 struct bootpc_ifcontext *ifctx,
264 struct bootpc_globalcontext *gctx);
265
266 static int bootpc_received(struct bootpc_globalcontext *gctx,
267 struct bootpc_ifcontext *ifctx);
268
269 static __inline int bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx);
270 static __inline int bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx);
271 static __inline int bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx);
272
273 /*
274 * In order to have multiple active interfaces with address 0.0.0.0
275 * and be able to send data to a selected interface, we perform
276 * some tricks:
277 *
278 * - The 'broadcast' address is different for each interface.
279 *
280 * - We temporarily add routing pointing 255.255.255.255 to the
281 * selected interface broadcast address, thus the packet sent
282 * goes to that interface.
283 */
284
285 #ifdef BOOTP_DEBUG
286 void
287 bootpboot_p_sa(struct sockaddr *sa, struct sockaddr *ma)
288 {
289
290 if (sa == NULL) {
291 printf("(sockaddr *) <null>");
292 return;
293 }
294 switch (sa->sa_family) {
295 case AF_INET:
296 {
297 struct sockaddr_in *sin;
298
299 sin = (struct sockaddr_in *) sa;
300 printf("inet ");
301 print_sin_addr(sin);
302 if (ma != NULL) {
303 sin = (struct sockaddr_in *) ma;
304 printf(" mask ");
305 print_sin_addr(sin);
306 }
307 }
308 break;
309 case AF_LINK:
310 {
311 struct sockaddr_dl *sli;
312 int i;
313
314 sli = (struct sockaddr_dl *) sa;
315 printf("link %.*s ", sli->sdl_nlen, sli->sdl_data);
316 for (i = 0; i < sli->sdl_alen; i++) {
317 if (i > 0)
318 printf(":");
319 printf("%x", ((unsigned char *) LLADDR(sli))[i]);
320 }
321 }
322 break;
323 default:
324 printf("af%d", sa->sa_family);
325 }
326 }
327
328 void
329 bootpboot_p_ma(struct sockaddr *ma)
330 {
331
332 if (ma == NULL) {
333 printf("<null>");
334 return;
335 }
336 printf("%x", *(int *)ma);
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_ma(rt->rt_genmask);
346 printf(" ");
347 bootpboot_p_sa(rt->rt_gateway, NULL);
348 printf(" ");
349 printf("flags %x", (unsigned short) rt->rt_flags);
350 printf(" %d", (int) rt->rt_rmx.rmx_expire);
351 printf(" %s\n", rt->rt_ifp->if_xname);
352 }
353
354 void
355 bootpboot_p_tree(struct radix_node *rn)
356 {
357
358 while (rn != NULL) {
359 if (rn->rn_bit < 0) {
360 if ((rn->rn_flags & RNF_ROOT) != 0) {
361 } else {
362 bootpboot_p_rtentry((struct rtentry *) rn);
363 }
364 rn = rn->rn_dupedkey;
365 } else {
366 bootpboot_p_tree(rn->rn_left);
367 bootpboot_p_tree(rn->rn_right);
368 return;
369 }
370 }
371 }
372
373 void
374 bootpboot_p_rtlist(void)
375 {
376
377 printf("Routing table:\n");
378 RADIX_NODE_LOCK(V_rt_tables[AF_INET]); /* could sleep XXX */
379 bootpboot_p_tree(V_rt_tables[AF_INET]->rnh_treetop);
380 RADIX_NODE_UNLOCK(V_rt_tables[AF_INET]);
381 }
382
383 void
384 bootpboot_p_if(struct ifnet *ifp, struct ifaddr *ifa)
385 {
386
387 printf("%s flags %x, addr ",
388 ifp->if_xname, ifp->if_flags);
389 print_sin_addr((struct sockaddr_in *) ifa->ifa_addr);
390 printf(", broadcast ");
391 print_sin_addr((struct sockaddr_in *) ifa->ifa_dstaddr);
392 printf(", netmask ");
393 print_sin_addr((struct sockaddr_in *) ifa->ifa_netmask);
394 printf("\n");
395 }
396
397 void
398 bootpboot_p_iflist(void)
399 {
400 struct ifnet *ifp;
401 struct ifaddr *ifa;
402
403 printf("Interface list:\n");
404 IFNET_RLOCK(); /* could sleep, but okay for debugging XXX */
405 for (ifp = TAILQ_FIRST(&V_ifnet);
406 ifp != NULL;
407 ifp = TAILQ_NEXT(ifp, if_link)) {
408 for (ifa = TAILQ_FIRST(&ifp->if_addrhead);
409 ifa != NULL;
410 ifa = TAILQ_NEXT(ifa, ifa_link))
411 if (ifa->ifa_addr->sa_family == AF_INET)
412 bootpboot_p_if(ifp, ifa);
413 }
414 IFNET_RUNLOCK();
415 }
416 #endif /* defined(BOOTP_DEBUG) */
417
418 static void
419 clear_sinaddr(struct sockaddr_in *sin)
420 {
421
422 bzero(sin, sizeof(*sin));
423 sin->sin_len = sizeof(*sin);
424 sin->sin_family = AF_INET;
425 sin->sin_addr.s_addr = INADDR_ANY; /* XXX: htonl(INAADDR_ANY) ? */
426 sin->sin_port = 0;
427 }
428
429 static void
430 allocifctx(struct bootpc_globalcontext *gctx)
431 {
432 struct bootpc_ifcontext *ifctx;
433 ifctx = (struct bootpc_ifcontext *) malloc(sizeof(*ifctx),
434 M_TEMP, M_WAITOK | M_ZERO);
435 if (ifctx == NULL)
436 panic("Failed to allocate bootp interface context structure");
437
438 ifctx->xid = gctx->xid;
439 #ifdef BOOTP_NO_DHCP
440 ifctx->state = IF_BOOTP_UNRESOLVED;
441 #else
442 ifctx->state = IF_DHCP_UNRESOLVED;
443 #endif
444 gctx->xid += 0x100;
445 if (gctx->interfaces != NULL)
446 gctx->lastinterface->next = ifctx;
447 else
448 gctx->interfaces = ifctx;
449 gctx->lastinterface = ifctx;
450 }
451
452 static __inline int
453 bootpc_ifctx_isresolved(struct bootpc_ifcontext *ifctx)
454 {
455
456 if (ifctx->state == IF_BOOTP_RESOLVED ||
457 ifctx->state == IF_DHCP_RESOLVED)
458 return 1;
459 return 0;
460 }
461
462 static __inline int
463 bootpc_ifctx_isunresolved(struct bootpc_ifcontext *ifctx)
464 {
465
466 if (ifctx->state == IF_BOOTP_UNRESOLVED ||
467 ifctx->state == IF_DHCP_UNRESOLVED)
468 return 1;
469 return 0;
470 }
471
472 static __inline int
473 bootpc_ifctx_isfailed(struct bootpc_ifcontext *ifctx)
474 {
475
476 if (ifctx->state == IF_BOOTP_FAILED ||
477 ifctx->state == IF_DHCP_FAILED)
478 return 1;
479 return 0;
480 }
481
482 static int
483 bootpc_received(struct bootpc_globalcontext *gctx,
484 struct bootpc_ifcontext *ifctx)
485 {
486 unsigned char dhcpreplytype;
487 char *p;
488
489 /*
490 * Need timeout for fallback to less
491 * desirable alternative.
492 */
493
494 /* This call used for the side effect (badopt flag) */
495 (void) bootpc_tag(&gctx->tmptag, &gctx->reply,
496 gctx->replylen,
497 TAG_END);
498
499 /* If packet is invalid, ignore it */
500 if (gctx->tmptag.badopt != 0)
501 return 0;
502
503 p = bootpc_tag(&gctx->tmptag, &gctx->reply,
504 gctx->replylen, TAG_DHCP_MSGTYPE);
505 if (p != NULL)
506 dhcpreplytype = *p;
507 else
508 dhcpreplytype = DHCP_NOMSG;
509
510 switch (ifctx->dhcpquerytype) {
511 case DHCP_DISCOVER:
512 if (dhcpreplytype != DHCP_OFFER /* Normal DHCP offer */
513 #ifndef BOOTP_FORCE_DHCP
514 && dhcpreplytype != DHCP_NOMSG /* Fallback to BOOTP */
515 #endif
516 )
517 return 0;
518 break;
519 case DHCP_REQUEST:
520 if (dhcpreplytype != DHCP_ACK)
521 return 0;
522 case DHCP_NOMSG:
523 break;
524 }
525
526 /* Ignore packet unless it gives us a root tag we didn't have */
527
528 if ((ifctx->state == IF_BOOTP_RESOLVED ||
529 (ifctx->dhcpquerytype == DHCP_DISCOVER &&
530 (ifctx->state == IF_DHCP_OFFERED ||
531 ifctx->state == IF_DHCP_RESOLVED))) &&
532 (bootpc_tag(&gctx->tmptag, &ifctx->reply,
533 ifctx->replylen,
534 TAG_ROOT) != NULL ||
535 bootpc_tag(&gctx->tmptag, &gctx->reply,
536 gctx->replylen,
537 TAG_ROOT) == NULL))
538 return 0;
539
540 bcopy(&gctx->reply, &ifctx->reply, gctx->replylen);
541 ifctx->replylen = gctx->replylen;
542
543 /* XXX: Only reset if 'perfect' response */
544 if (ifctx->state == IF_BOOTP_UNRESOLVED)
545 ifctx->state = IF_BOOTP_RESOLVED;
546 else if (ifctx->state == IF_DHCP_UNRESOLVED &&
547 ifctx->dhcpquerytype == DHCP_DISCOVER) {
548 if (dhcpreplytype == DHCP_OFFER)
549 ifctx->state = IF_DHCP_OFFERED;
550 else
551 ifctx->state = IF_BOOTP_RESOLVED; /* Fallback */
552 } else if (ifctx->state == IF_DHCP_OFFERED &&
553 ifctx->dhcpquerytype == DHCP_REQUEST)
554 ifctx->state = IF_DHCP_RESOLVED;
555
556
557 if (ifctx->dhcpquerytype == DHCP_DISCOVER &&
558 ifctx->state != IF_BOOTP_RESOLVED) {
559 p = bootpc_tag(&gctx->tmptag, &ifctx->reply,
560 ifctx->replylen, TAG_DHCP_SERVERID);
561 if (p != NULL && gctx->tmptag.taglen == 4) {
562 memcpy(&ifctx->dhcpserver, p, 4);
563 ifctx->gotdhcpserver = 1;
564 } else
565 ifctx->gotdhcpserver = 0;
566 return 1;
567 }
568
569 ifctx->gotrootpath = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
570 ifctx->replylen,
571 TAG_ROOT) != NULL);
572 ifctx->gotgw = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
573 ifctx->replylen,
574 TAG_ROUTERS) != NULL);
575 ifctx->gotnetmask = (bootpc_tag(&gctx->tmptag, &ifctx->reply,
576 ifctx->replylen,
577 TAG_SUBNETMASK) != NULL);
578 return 1;
579 }
580
581 static int
582 bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
583 {
584 struct socket *so;
585 struct sockaddr_in *sin, dst;
586 struct uio auio;
587 struct sockopt sopt;
588 struct iovec aio;
589 int error, on, rcvflg, timo, len;
590 time_t atimo;
591 time_t rtimo;
592 struct timeval tv;
593 struct bootpc_ifcontext *ifctx;
594 int outstanding;
595 int gotrootpath;
596 int retry;
597 const char *s;
598
599 /*
600 * Create socket and set its recieve timeout.
601 */
602 error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_ucred, td);
603 if (error != 0)
604 goto out0;
605
606 tv.tv_sec = 1;
607 tv.tv_usec = 0;
608 bzero(&sopt, sizeof(sopt));
609 sopt.sopt_dir = SOPT_SET;
610 sopt.sopt_level = SOL_SOCKET;
611 sopt.sopt_name = SO_RCVTIMEO;
612 sopt.sopt_val = &tv;
613 sopt.sopt_valsize = sizeof tv;
614
615 error = sosetopt(so, &sopt);
616 if (error != 0)
617 goto out;
618
619 /*
620 * Enable broadcast.
621 */
622 on = 1;
623 sopt.sopt_name = SO_BROADCAST;
624 sopt.sopt_val = &on;
625 sopt.sopt_valsize = sizeof on;
626
627 error = sosetopt(so, &sopt);
628 if (error != 0)
629 goto out;
630
631 /*
632 * Disable routing.
633 */
634
635 on = 1;
636 sopt.sopt_name = SO_DONTROUTE;
637 sopt.sopt_val = &on;
638 sopt.sopt_valsize = sizeof on;
639
640 error = sosetopt(so, &sopt);
641 if (error != 0)
642 goto out;
643
644 /*
645 * Bind the local endpoint to a bootp client port.
646 */
647 sin = &dst;
648 clear_sinaddr(sin);
649 sin->sin_port = htons(IPPORT_BOOTPC);
650 error = sobind(so, (struct sockaddr *)sin, td);
651 if (error != 0) {
652 printf("bind failed\n");
653 goto out;
654 }
655
656 /*
657 * Setup socket address for the server.
658 */
659 sin = &dst;
660 clear_sinaddr(sin);
661 sin->sin_addr.s_addr = INADDR_BROADCAST;
662 sin->sin_port = htons(IPPORT_BOOTPS);
663
664 /*
665 * Send it, repeatedly, until a reply is received,
666 * but delay each re-send by an increasing amount.
667 * If the delay hits the maximum, start complaining.
668 */
669 timo = 0;
670 rtimo = 0;
671 for (;;) {
672
673 outstanding = 0;
674 gotrootpath = 0;
675
676 for (ifctx = gctx->interfaces;
677 ifctx != NULL;
678 ifctx = ifctx->next) {
679 if (bootpc_ifctx_isresolved(ifctx) != 0 &&
680 bootpc_tag(&gctx->tmptag, &ifctx->reply,
681 ifctx->replylen,
682 TAG_ROOT) != NULL)
683 gotrootpath = 1;
684 }
685
686 for (ifctx = gctx->interfaces;
687 ifctx != NULL;
688 ifctx = ifctx->next) {
689 ifctx->outstanding = 0;
690 if (bootpc_ifctx_isresolved(ifctx) != 0 &&
691 gotrootpath != 0) {
692 continue;
693 }
694 if (bootpc_ifctx_isfailed(ifctx) != 0)
695 continue;
696
697 outstanding++;
698 ifctx->outstanding = 1;
699
700 /* Proceed to next step in DHCP negotiation */
701 if ((ifctx->state == IF_DHCP_OFFERED &&
702 ifctx->dhcpquerytype != DHCP_REQUEST) ||
703 (ifctx->state == IF_DHCP_UNRESOLVED &&
704 ifctx->dhcpquerytype != DHCP_DISCOVER) ||
705 (ifctx->state == IF_BOOTP_UNRESOLVED &&
706 ifctx->dhcpquerytype != DHCP_NOMSG)) {
707 ifctx->sentmsg = 0;
708 bootpc_compose_query(ifctx, gctx, td);
709 }
710
711 /* Send BOOTP request (or re-send). */
712
713 if (ifctx->sentmsg == 0) {
714 switch(ifctx->dhcpquerytype) {
715 case DHCP_DISCOVER:
716 s = "DHCP Discover";
717 break;
718 case DHCP_REQUEST:
719 s = "DHCP Request";
720 break;
721 case DHCP_NOMSG:
722 default:
723 s = "BOOTP Query";
724 break;
725 }
726 printf("Sending %s packet from "
727 "interface %s (%*D)\n",
728 s,
729 ifctx->ireq.ifr_name,
730 ifctx->sdl->sdl_alen,
731 (unsigned char *) LLADDR(ifctx->sdl),
732 ":");
733 ifctx->sentmsg = 1;
734 }
735
736 aio.iov_base = (caddr_t) &ifctx->call;
737 aio.iov_len = sizeof(ifctx->call);
738
739 auio.uio_iov = &aio;
740 auio.uio_iovcnt = 1;
741 auio.uio_segflg = UIO_SYSSPACE;
742 auio.uio_rw = UIO_WRITE;
743 auio.uio_offset = 0;
744 auio.uio_resid = sizeof(ifctx->call);
745 auio.uio_td = td;
746
747 /* Set netmask to 0.0.0.0 */
748
749 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
750 clear_sinaddr(sin);
751 error = ifioctl(ifctx->so, SIOCSIFNETMASK,
752 (caddr_t) &ifctx->ireq, td);
753 if (error != 0)
754 panic("bootpc_call:"
755 "set if netmask, error=%d",
756 error);
757
758 error = sosend(so, (struct sockaddr *) &dst,
759 &auio, NULL, NULL, 0, td);
760 if (error != 0) {
761 printf("bootpc_call: sosend: %d state %08x\n",
762 error, (int) so->so_state);
763 }
764
765 /* XXX: Is this needed ? */
766 pause("bootpw", hz/10);
767
768 /* Set netmask to 255.0.0.0 */
769
770 sin = (struct sockaddr_in *) &ifctx->ireq.ifr_addr;
771 clear_sinaddr(sin);
772 sin->sin_addr.s_addr = htonl(0xff000000u);
773 error = ifioctl(ifctx->so, SIOCSIFNETMASK,
774 (caddr_t) &ifctx->ireq, td);
775 if (error != 0)
776 panic("bootpc_call:"
777 "set if netmask, error=%d",
778 error);
779
780 }
781
782 if (outstanding == 0 &&
783 (rtimo == 0 || time_second >= rtimo)) {
784 error = 0;
785 goto gotreply;
786 }
787
788 /* Determine new timeout. */
789 if (timo < MAX_RESEND_DELAY)
790 timo++;
791 else {
792 printf("DHCP/BOOTP timeout for server ");
793 print_sin_addr(&dst);
794 printf("\n");
795 }
796
797 /*
798 * Wait for up to timo seconds for a reply.
799 * The socket receive timeout was set to 1 second.
800 */
801 atimo = timo + time_second;
802 while (time_second < atimo) {
803 aio.iov_base = (caddr_t) &gctx->reply;
804 aio.iov_len = sizeof(gctx->reply);
805
806 auio.uio_iov = &aio;
807 auio.uio_iovcnt = 1;
808 auio.uio_segflg = UIO_SYSSPACE;
809 auio.uio_rw = UIO_READ;
810 auio.uio_offset = 0;
811 auio.uio_resid = sizeof(gctx->reply);
812 auio.uio_td = td;
813
814 rcvflg = 0;
815 error = soreceive(so, NULL, &auio,
816 NULL, NULL, &rcvflg);
817 gctx->secs = time_second - gctx->starttime;
818 for (ifctx = gctx->interfaces;
819 ifctx != NULL;
820 ifctx = ifctx->next) {
821 if (bootpc_ifctx_isresolved(ifctx) != 0 ||
822 bootpc_ifctx_isfailed(ifctx) != 0)
823 continue;
824
825 ifctx->call.secs = htons(gctx->secs);
826 }
827 if (error == EWOULDBLOCK)
828 continue;
829 if (error != 0)
830 goto out;
831 len = sizeof(gctx->reply) - auio.uio_resid;
832
833 /* Do we have the required number of bytes ? */
834 if (len < BOOTP_MIN_LEN)
835 continue;
836 gctx->replylen = len;
837
838 /* Is it a reply? */
839 if (gctx->reply.op != BOOTP_REPLY)
840 continue;
841
842 /* Is this an answer to our query */
843 for (ifctx = gctx->interfaces;
844 ifctx != NULL;
845 ifctx = ifctx->next) {
846 if (gctx->reply.xid != ifctx->call.xid)
847 continue;
848
849 /* Same HW address size ? */
850 if (gctx->reply.hlen != ifctx->call.hlen)
851 continue;
852
853 /* Correct HW address ? */
854 if (bcmp(gctx->reply.chaddr,
855 ifctx->call.chaddr,
856 ifctx->call.hlen) != 0)
857 continue;
858
859 break;
860 }
861
862 if (ifctx != NULL) {
863 s = bootpc_tag(&gctx->tmptag,
864 &gctx->reply,
865 gctx->replylen,
866 TAG_DHCP_MSGTYPE);
867 if (s != NULL) {
868 switch (*s) {
869 case DHCP_OFFER:
870 s = "DHCP Offer";
871 break;
872 case DHCP_ACK:
873 s = "DHCP Ack";
874 break;
875 default:
876 s = "DHCP (unexpected)";
877 break;
878 }
879 } else
880 s = "BOOTP Reply";
881
882 printf("Received %s packet"
883 " on %s from ",
884 s,
885 ifctx->ireq.ifr_name);
886 print_in_addr(gctx->reply.siaddr);
887 if (gctx->reply.giaddr.s_addr !=
888 htonl(INADDR_ANY)) {
889 printf(" via ");
890 print_in_addr(gctx->reply.giaddr);
891 }
892 if (bootpc_received(gctx, ifctx) != 0) {
893 printf(" (accepted)");
894 if (ifctx->outstanding) {
895 ifctx->outstanding = 0;
896 outstanding--;
897 }
898 /* Network settle delay */
899 if (outstanding == 0)
900 atimo = time_second +
901 BOOTP_SETTLE_DELAY;
902 } else
903 printf(" (ignored)");
904 if (ifctx->gotrootpath) {
905 gotrootpath = 1;
906 rtimo = time_second +
907 BOOTP_SETTLE_DELAY;
908 printf(" (got root path)");
909 } else
910 printf(" (no root path)");
911 printf("\n");
912 }
913 } /* while secs */
914 #ifdef BOOTP_TIMEOUT
915 if (gctx->secs > BOOTP_TIMEOUT && BOOTP_TIMEOUT > 0)
916 break;
917 #endif
918 /* Force a retry if halfway in DHCP negotiation */
919 retry = 0;
920 for (ifctx = gctx->interfaces; ifctx != NULL;
921 ifctx = ifctx->next) {
922 if (ifctx->state == IF_DHCP_OFFERED) {
923 if (ifctx->dhcpquerytype == DHCP_DISCOVER)
924 retry = 1;
925 else
926 ifctx->state = IF_DHCP_UNRESOLVED;
927 }
928 }
929
930 if (retry != 0)
931 continue;
932
933 if (gotrootpath != 0) {
934 gctx->gotrootpath = gotrootpath;
935 if (rtimo != 0 && time_second >= rtimo)
936 break;
937 }
938 } /* forever send/receive */
939
940 /*
941 * XXX: These are errors of varying seriousness being silently
942 * ignored
943 */
944
945 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
946 if (bootpc_ifctx_isresolved(ifctx) == 0) {
947 printf("%s timeout for interface %s\n",
948 ifctx->dhcpquerytype != DHCP_NOMSG ?
949 "DHCP" : "BOOTP",
950 ifctx->ireq.ifr_name);
951 }
952 }
953 if (gctx->gotrootpath != 0) {
954 #if 0
955 printf("Got a root path, ignoring remaining timeout\n");
956 #endif
957 error = 0;
958 goto out;
959 }
960 #ifndef BOOTP_NFSROOT
961 for (ifctx = gctx->interfaces; ifctx != NULL; ifctx = ifctx->next) {
962 if (bootpc_ifctx_isresolved(ifctx) != 0) {
963 error = 0;
964 goto out;
965 }
966 }
967 #endif
968 error = ETIMEDOUT;
969 goto out;
970
971 gotreply:
972 out:
973 soclose(so);
974 out0:
975 return error;
976 }
977
978 static int
979 bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
980 struct bootpc_globalcontext *gctx, struct thread *td)
981 {
982 struct sockaddr_in *sin;
983 int error;
984 struct ifreq *ireq;
985 struct socket *so;
986 struct ifaddr *ifa;
987 struct sockaddr_dl *sdl;
988
989 error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td->td_ucred, td);
990 if (error != 0)
991 panic("nfs_boot: socreate, error=%d", error);
992
993 ireq = &ifctx->ireq;
994 so = ifctx->so;
995
996 /*
997 * Bring up the interface.
998 *
999 * Get the old interface flags and or IFF_UP into them; if
1000 * IFF_UP set blindly, interface selection can be clobbered.
1001 */
1002 error = ifioctl(so, |