]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/nfs/bootp_subr.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / 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 < '0') || (*p > '9'))
1176                 return -1;
1177         while ((*p >= '0') && (*p <= '9')) {
1178                 ret = ret * 10 + (*p - '0');
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);