xref: /xnu-11417.140.69/bsd/kern/netboot.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1*43a90889SApple OSS Distributions /*
2*43a90889SApple OSS Distributions  * Copyright (c) 2001-2019 Apple Inc. All rights reserved.
3*43a90889SApple OSS Distributions  *
4*43a90889SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*43a90889SApple OSS Distributions  *
6*43a90889SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*43a90889SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*43a90889SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*43a90889SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*43a90889SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*43a90889SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*43a90889SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*43a90889SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*43a90889SApple OSS Distributions  *
15*43a90889SApple OSS Distributions  * Please obtain a copy of the License at
16*43a90889SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*43a90889SApple OSS Distributions  *
18*43a90889SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*43a90889SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*43a90889SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*43a90889SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*43a90889SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*43a90889SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*43a90889SApple OSS Distributions  * limitations under the License.
25*43a90889SApple OSS Distributions  *
26*43a90889SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*43a90889SApple OSS Distributions  */
28*43a90889SApple OSS Distributions 
29*43a90889SApple OSS Distributions /*
30*43a90889SApple OSS Distributions  * History:
31*43a90889SApple OSS Distributions  * 14 December, 2001	Dieter Siegmund ([email protected])
32*43a90889SApple OSS Distributions  * - created
33*43a90889SApple OSS Distributions  */
34*43a90889SApple OSS Distributions #include <sys/param.h>
35*43a90889SApple OSS Distributions #include <sys/systm.h>
36*43a90889SApple OSS Distributions #include <sys/kernel.h>
37*43a90889SApple OSS Distributions #include <sys/conf.h>
38*43a90889SApple OSS Distributions #include <sys/ioctl.h>
39*43a90889SApple OSS Distributions #include <sys/proc_internal.h>
40*43a90889SApple OSS Distributions #include <sys/mount_internal.h>
41*43a90889SApple OSS Distributions #include <sys/mbuf.h>
42*43a90889SApple OSS Distributions #include <sys/filedesc.h>
43*43a90889SApple OSS Distributions #include <sys/vnode_internal.h>
44*43a90889SApple OSS Distributions #include <sys/malloc.h>
45*43a90889SApple OSS Distributions #include <sys/socket.h>
46*43a90889SApple OSS Distributions #include <sys/socketvar.h>
47*43a90889SApple OSS Distributions #include <sys/reboot.h>
48*43a90889SApple OSS Distributions #include <sys/kauth.h>
49*43a90889SApple OSS Distributions #include <net/if.h>
50*43a90889SApple OSS Distributions #include <net/if_dl.h>
51*43a90889SApple OSS Distributions #include <net/if_types.h>
52*43a90889SApple OSS Distributions #include <net/route.h>
53*43a90889SApple OSS Distributions #include <netinet/in.h>
54*43a90889SApple OSS Distributions #include <netinet/if_ether.h>
55*43a90889SApple OSS Distributions #include <netinet/dhcp_options.h>
56*43a90889SApple OSS Distributions 
57*43a90889SApple OSS Distributions #include <kern/kern_types.h>
58*43a90889SApple OSS Distributions #include <kern/kalloc.h>
59*43a90889SApple OSS Distributions #include <sys/netboot.h>
60*43a90889SApple OSS Distributions #include <sys/imageboot.h>
61*43a90889SApple OSS Distributions #include <pexpert/pexpert.h>
62*43a90889SApple OSS Distributions 
63*43a90889SApple OSS Distributions extern int (*mountroot)(void);
64*43a90889SApple OSS Distributions 
65*43a90889SApple OSS Distributions extern unsigned char    rootdevice[];
66*43a90889SApple OSS Distributions 
67*43a90889SApple OSS Distributions static int                      S_netboot = 0;
68*43a90889SApple OSS Distributions static struct netboot_info *    S_netboot_info_p;
69*43a90889SApple OSS Distributions 
70*43a90889SApple OSS Distributions void *
71*43a90889SApple OSS Distributions IOBSDRegistryEntryForDeviceTree(const char * path);
72*43a90889SApple OSS Distributions 
73*43a90889SApple OSS Distributions void
74*43a90889SApple OSS Distributions IOBSDRegistryEntryRelease(void * entry);
75*43a90889SApple OSS Distributions 
76*43a90889SApple OSS Distributions const void *
77*43a90889SApple OSS Distributions IOBSDRegistryEntryGetData(void * entry, const char * property_name,
78*43a90889SApple OSS Distributions     int * packet_length);
79*43a90889SApple OSS Distributions 
80*43a90889SApple OSS Distributions #define BOOTP_RESPONSE  "bootp-response"
81*43a90889SApple OSS Distributions #define BSDP_RESPONSE   "bsdp-response"
82*43a90889SApple OSS Distributions #define DHCP_RESPONSE   "dhcp-response"
83*43a90889SApple OSS Distributions 
84*43a90889SApple OSS Distributions #define IP_FORMAT       "%d.%d.%d.%d"
85*43a90889SApple OSS Distributions #define IP_CH(ip)       ((u_char *)ip)
86*43a90889SApple OSS Distributions #define IP_LIST(ip)     IP_CH(ip)[0],IP_CH(ip)[1],IP_CH(ip)[2],IP_CH(ip)[3]
87*43a90889SApple OSS Distributions 
88*43a90889SApple OSS Distributions #define kNetBootRootPathPrefixNFS       "nfs:"
89*43a90889SApple OSS Distributions #define kNetBootRootPathPrefixHTTP      "http:"
90*43a90889SApple OSS Distributions 
91*43a90889SApple OSS Distributions typedef enum {
92*43a90889SApple OSS Distributions 	kNetBootImageTypeUnknown = 0,
93*43a90889SApple OSS Distributions 	kNetBootImageTypeNFS = 1, // Deprecated
94*43a90889SApple OSS Distributions 	kNetBootImageTypeHTTP = 2,
95*43a90889SApple OSS Distributions } NetBootImageType;
96*43a90889SApple OSS Distributions 
97*43a90889SApple OSS Distributions struct netboot_info {
98*43a90889SApple OSS Distributions 	struct in_addr      client_ip;
99*43a90889SApple OSS Distributions 	struct in_addr      server_ip;
100*43a90889SApple OSS Distributions 	char *              server_name;
101*43a90889SApple OSS Distributions 	size_t              server_name_length;
102*43a90889SApple OSS Distributions 	char *              mount_point;
103*43a90889SApple OSS Distributions 	size_t              mount_point_length;
104*43a90889SApple OSS Distributions 	char *              image_path;
105*43a90889SApple OSS Distributions 	size_t              image_path_length;
106*43a90889SApple OSS Distributions 	NetBootImageType    image_type;
107*43a90889SApple OSS Distributions 	char *              second_image_path;
108*43a90889SApple OSS Distributions 	size_t              second_image_path_length;
109*43a90889SApple OSS Distributions };
110*43a90889SApple OSS Distributions 
111*43a90889SApple OSS Distributions /*
112*43a90889SApple OSS Distributions  * Function: parse_booter_path
113*43a90889SApple OSS Distributions  * Purpose:
114*43a90889SApple OSS Distributions  *   Parse a string of the form:
115*43a90889SApple OSS Distributions  *        "<IP>:<host>:<mount>[:<image_path>]"
116*43a90889SApple OSS Distributions  *   into the given ip address, host, mount point, and optionally, image_path.
117*43a90889SApple OSS Distributions  *
118*43a90889SApple OSS Distributions  * Note:
119*43a90889SApple OSS Distributions  *   The passed in string is modified i.e. ':' is replaced by '\0'.
120*43a90889SApple OSS Distributions  * Example:
121*43a90889SApple OSS Distributions  *   "17.202.16.17:seaport:/release/.images/Image9/CurrentHera"
122*43a90889SApple OSS Distributions  */
123*43a90889SApple OSS Distributions static __inline__ boolean_t
parse_booter_path(char * path,struct in_addr * iaddr_p,char const ** host,char ** mount_dir,char ** image_path)124*43a90889SApple OSS Distributions parse_booter_path(char * path, struct in_addr * iaddr_p, char const * * host,
125*43a90889SApple OSS Distributions     char * * mount_dir, char * * image_path)
126*43a90889SApple OSS Distributions {
127*43a90889SApple OSS Distributions 	char *      start;
128*43a90889SApple OSS Distributions 	char *      colon;
129*43a90889SApple OSS Distributions 
130*43a90889SApple OSS Distributions 	/* IP address */
131*43a90889SApple OSS Distributions 	start = path;
132*43a90889SApple OSS Distributions 	colon = strchr(start, ':');
133*43a90889SApple OSS Distributions 	if (colon == NULL) {
134*43a90889SApple OSS Distributions 		return FALSE;
135*43a90889SApple OSS Distributions 	}
136*43a90889SApple OSS Distributions 	*colon = '\0';
137*43a90889SApple OSS Distributions 	if (inet_aton(start, iaddr_p) != 1) {
138*43a90889SApple OSS Distributions 		return FALSE;
139*43a90889SApple OSS Distributions 	}
140*43a90889SApple OSS Distributions 
141*43a90889SApple OSS Distributions 	/* host */
142*43a90889SApple OSS Distributions 	start = colon + 1;
143*43a90889SApple OSS Distributions 	colon = strchr(start, ':');
144*43a90889SApple OSS Distributions 	if (colon == NULL) {
145*43a90889SApple OSS Distributions 		return FALSE;
146*43a90889SApple OSS Distributions 	}
147*43a90889SApple OSS Distributions 	*colon = '\0';
148*43a90889SApple OSS Distributions 	*host = start;
149*43a90889SApple OSS Distributions 
150*43a90889SApple OSS Distributions 	/* mount */
151*43a90889SApple OSS Distributions 	start = colon + 1;
152*43a90889SApple OSS Distributions 	colon = strchr(start, ':');
153*43a90889SApple OSS Distributions 	*mount_dir = start;
154*43a90889SApple OSS Distributions 	if (colon == NULL) {
155*43a90889SApple OSS Distributions 		*image_path = NULL;
156*43a90889SApple OSS Distributions 	} else {
157*43a90889SApple OSS Distributions 		/* image path */
158*43a90889SApple OSS Distributions 		*colon = '\0';
159*43a90889SApple OSS Distributions 		start = colon + 1;
160*43a90889SApple OSS Distributions 		*image_path = start;
161*43a90889SApple OSS Distributions 	}
162*43a90889SApple OSS Distributions 	return TRUE;
163*43a90889SApple OSS Distributions }
164*43a90889SApple OSS Distributions 
165*43a90889SApple OSS Distributions /*
166*43a90889SApple OSS Distributions  * Function: find_colon
167*43a90889SApple OSS Distributions  * Purpose:
168*43a90889SApple OSS Distributions  *   Find the next unescaped instance of the colon character.
169*43a90889SApple OSS Distributions  *   If a colon is escaped (preceded by a backslash '\' character),
170*43a90889SApple OSS Distributions  *   shift the string over by one character to overwrite the backslash.
171*43a90889SApple OSS Distributions  */
172*43a90889SApple OSS Distributions static __inline__ char *
find_colon(char * str)173*43a90889SApple OSS Distributions find_colon(char * str)
174*43a90889SApple OSS Distributions {
175*43a90889SApple OSS Distributions 	char * start = str;
176*43a90889SApple OSS Distributions 	char * colon;
177*43a90889SApple OSS Distributions 
178*43a90889SApple OSS Distributions 	while ((colon = strchr(start, ':')) != NULL) {
179*43a90889SApple OSS Distributions 		char * dst;
180*43a90889SApple OSS Distributions 		char * src;
181*43a90889SApple OSS Distributions 
182*43a90889SApple OSS Distributions 		if (colon == start) {
183*43a90889SApple OSS Distributions 			break;
184*43a90889SApple OSS Distributions 		}
185*43a90889SApple OSS Distributions 		if (colon[-1] != '\\') {
186*43a90889SApple OSS Distributions 			break;
187*43a90889SApple OSS Distributions 		}
188*43a90889SApple OSS Distributions 		for (dst = colon - 1, src = colon; *dst != '\0'; dst++, src++) {
189*43a90889SApple OSS Distributions 			*dst = *src;
190*43a90889SApple OSS Distributions 		}
191*43a90889SApple OSS Distributions 		start = colon;
192*43a90889SApple OSS Distributions 	}
193*43a90889SApple OSS Distributions 	return colon;
194*43a90889SApple OSS Distributions }
195*43a90889SApple OSS Distributions 
196*43a90889SApple OSS Distributions /*
197*43a90889SApple OSS Distributions  * Function: parse_netboot_path
198*43a90889SApple OSS Distributions  * Purpose:
199*43a90889SApple OSS Distributions  *   Parse a string of the form:
200*43a90889SApple OSS Distributions  *        "nfs:<IP>:<mount>[:<image_path>]"
201*43a90889SApple OSS Distributions  *   into the given ip address, host, mount point, and optionally, image_path.
202*43a90889SApple OSS Distributions  * Notes:
203*43a90889SApple OSS Distributions  * - the passed in string is modified i.e. ':' is replaced by '\0'
204*43a90889SApple OSS Distributions  * - literal colons must be escaped with a backslash
205*43a90889SApple OSS Distributions  *
206*43a90889SApple OSS Distributions  * Examples:
207*43a90889SApple OSS Distributions  * nfs:17.202.42.112:/Library/NetBoot/NetBootSP0:Jaguar/Jaguar.dmg
208*43a90889SApple OSS Distributions  * nfs:17.202.42.112:/Volumes/Foo\:/Library/NetBoot/NetBootSP0:Jaguar/Jaguar.dmg
209*43a90889SApple OSS Distributions  */
210*43a90889SApple OSS Distributions static __inline__ boolean_t
parse_netboot_path(char * path,struct in_addr * iaddr_p,char const ** host,char ** mount_dir,char ** image_path)211*43a90889SApple OSS Distributions parse_netboot_path(char * path, struct in_addr * iaddr_p, char const * * host,
212*43a90889SApple OSS Distributions     char * * mount_dir, char * * image_path)
213*43a90889SApple OSS Distributions {
214*43a90889SApple OSS Distributions 	static char tmp[MAX_IPv4_STR_LEN]; /* Danger - not thread safe */
215*43a90889SApple OSS Distributions 	char *      start;
216*43a90889SApple OSS Distributions 	char *      colon;
217*43a90889SApple OSS Distributions 
218*43a90889SApple OSS Distributions 	if (strncmp(path, kNetBootRootPathPrefixNFS,
219*43a90889SApple OSS Distributions 	    strlen(kNetBootRootPathPrefixNFS)) != 0) {
220*43a90889SApple OSS Distributions 		return FALSE;
221*43a90889SApple OSS Distributions 	}
222*43a90889SApple OSS Distributions 
223*43a90889SApple OSS Distributions 	/* IP address */
224*43a90889SApple OSS Distributions 	start = path + strlen(kNetBootRootPathPrefixNFS);
225*43a90889SApple OSS Distributions 	colon = strchr(start, ':');
226*43a90889SApple OSS Distributions 	if (colon == NULL) {
227*43a90889SApple OSS Distributions 		return FALSE;
228*43a90889SApple OSS Distributions 	}
229*43a90889SApple OSS Distributions 	*colon = '\0';
230*43a90889SApple OSS Distributions 	if (inet_aton(start, iaddr_p) != 1) {
231*43a90889SApple OSS Distributions 		return FALSE;
232*43a90889SApple OSS Distributions 	}
233*43a90889SApple OSS Distributions 
234*43a90889SApple OSS Distributions 	/* mount point */
235*43a90889SApple OSS Distributions 	start = colon + 1;
236*43a90889SApple OSS Distributions 	colon = find_colon(start);
237*43a90889SApple OSS Distributions 	*mount_dir = start;
238*43a90889SApple OSS Distributions 	if (colon == NULL) {
239*43a90889SApple OSS Distributions 		*image_path = NULL;
240*43a90889SApple OSS Distributions 	} else {
241*43a90889SApple OSS Distributions 		/* image path */
242*43a90889SApple OSS Distributions 		*colon = '\0';
243*43a90889SApple OSS Distributions 		start = colon + 1;
244*43a90889SApple OSS Distributions 		(void)find_colon(start);
245*43a90889SApple OSS Distributions 		*image_path = start;
246*43a90889SApple OSS Distributions 	}
247*43a90889SApple OSS Distributions 	*host = inet_ntop(AF_INET, iaddr_p, tmp, sizeof(tmp));
248*43a90889SApple OSS Distributions 	return TRUE;
249*43a90889SApple OSS Distributions }
250*43a90889SApple OSS Distributions 
251*43a90889SApple OSS Distributions static boolean_t
parse_image_path(char * path,struct in_addr * iaddr_p,char const ** host,char ** mount_dir,char ** image_path)252*43a90889SApple OSS Distributions parse_image_path(char * path, struct in_addr * iaddr_p, char const * * host,
253*43a90889SApple OSS Distributions     char * * mount_dir, char * * image_path)
254*43a90889SApple OSS Distributions {
255*43a90889SApple OSS Distributions 	if (path[0] >= '0' && path[0] <= '9') {
256*43a90889SApple OSS Distributions 		return parse_booter_path(path, iaddr_p, host, mount_dir,
257*43a90889SApple OSS Distributions 		           image_path);
258*43a90889SApple OSS Distributions 	}
259*43a90889SApple OSS Distributions 	return parse_netboot_path(path, iaddr_p, host, mount_dir,
260*43a90889SApple OSS Distributions 	           image_path);
261*43a90889SApple OSS Distributions }
262*43a90889SApple OSS Distributions 
263*43a90889SApple OSS Distributions static boolean_t
get_root_path(char * root_path)264*43a90889SApple OSS Distributions get_root_path(char * root_path)
265*43a90889SApple OSS Distributions {
266*43a90889SApple OSS Distributions 	void *              entry;
267*43a90889SApple OSS Distributions 	boolean_t           found = FALSE;
268*43a90889SApple OSS Distributions 	const void *        pkt;
269*43a90889SApple OSS Distributions 	int                 pkt_len;
270*43a90889SApple OSS Distributions 
271*43a90889SApple OSS Distributions 	entry = IOBSDRegistryEntryForDeviceTree("/chosen");
272*43a90889SApple OSS Distributions 	if (entry == NULL) {
273*43a90889SApple OSS Distributions 		return FALSE;
274*43a90889SApple OSS Distributions 	}
275*43a90889SApple OSS Distributions 	pkt = IOBSDRegistryEntryGetData(entry, BSDP_RESPONSE, &pkt_len);
276*43a90889SApple OSS Distributions 	if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
277*43a90889SApple OSS Distributions 		printf("netboot: retrieving root path from BSDP response\n");
278*43a90889SApple OSS Distributions 	} else {
279*43a90889SApple OSS Distributions 		pkt = IOBSDRegistryEntryGetData(entry, BOOTP_RESPONSE,
280*43a90889SApple OSS Distributions 		    &pkt_len);
281*43a90889SApple OSS Distributions 		if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
282*43a90889SApple OSS Distributions 			printf("netboot: retrieving root path from BOOTP response\n");
283*43a90889SApple OSS Distributions 		}
284*43a90889SApple OSS Distributions 	}
285*43a90889SApple OSS Distributions 	if (pkt != NULL) {
286*43a90889SApple OSS Distributions 		int                     len;
287*43a90889SApple OSS Distributions 		dhcpol_t                options;
288*43a90889SApple OSS Distributions 		const char *            path;
289*43a90889SApple OSS Distributions 		const struct dhcp *     reply;
290*43a90889SApple OSS Distributions 
291*43a90889SApple OSS Distributions 		reply = (const struct dhcp *)pkt;
292*43a90889SApple OSS Distributions 		(void)dhcpol_parse_packet(&options, reply, pkt_len);
293*43a90889SApple OSS Distributions 
294*43a90889SApple OSS Distributions 		path = (const char *)dhcpol_find(&options,
295*43a90889SApple OSS Distributions 		    dhcptag_root_path_e, &len, NULL);
296*43a90889SApple OSS Distributions 		if (path) {
297*43a90889SApple OSS Distributions 			memcpy(root_path, path, len);
298*43a90889SApple OSS Distributions 			root_path[len] = '\0';
299*43a90889SApple OSS Distributions 			found = TRUE;
300*43a90889SApple OSS Distributions 		}
301*43a90889SApple OSS Distributions 	}
302*43a90889SApple OSS Distributions 	IOBSDRegistryEntryRelease(entry);
303*43a90889SApple OSS Distributions 	return found;
304*43a90889SApple OSS Distributions }
305*43a90889SApple OSS Distributions 
306*43a90889SApple OSS Distributions static void
save_path(char ** str_p,size_t * length_p,char * path)307*43a90889SApple OSS Distributions save_path(char * * str_p, size_t * length_p, char * path)
308*43a90889SApple OSS Distributions {
309*43a90889SApple OSS Distributions 	*length_p = strlen(path) + 1;
310*43a90889SApple OSS Distributions 	*str_p = kalloc_data(*length_p, Z_WAITOK);
311*43a90889SApple OSS Distributions 	strlcpy(*str_p, path, *length_p);
312*43a90889SApple OSS Distributions 	return;
313*43a90889SApple OSS Distributions }
314*43a90889SApple OSS Distributions 
315*43a90889SApple OSS Distributions static struct netboot_info *
netboot_info_init(struct in_addr iaddr)316*43a90889SApple OSS Distributions netboot_info_init(struct in_addr iaddr)
317*43a90889SApple OSS Distributions {
318*43a90889SApple OSS Distributions 	boolean_t                   have_root_path = FALSE;
319*43a90889SApple OSS Distributions 	struct netboot_info *       info = NULL;
320*43a90889SApple OSS Distributions 	char *                      root_path = NULL;
321*43a90889SApple OSS Distributions 
322*43a90889SApple OSS Distributions 	info = (struct netboot_info *)kalloc_type(struct netboot_info, Z_WAITOK | Z_ZERO);
323*43a90889SApple OSS Distributions 	info->client_ip = iaddr;
324*43a90889SApple OSS Distributions 	info->image_type = kNetBootImageTypeUnknown;
325*43a90889SApple OSS Distributions 
326*43a90889SApple OSS Distributions 	/* check for a booter-specified path then a NetBoot path */
327*43a90889SApple OSS Distributions 	root_path = zalloc(ZV_NAMEI);
328*43a90889SApple OSS Distributions 
329*43a90889SApple OSS Distributions 	if (PE_parse_boot_argn("rp0", root_path, MAXPATHLEN) == TRUE
330*43a90889SApple OSS Distributions 	    || PE_parse_boot_argn("rp", root_path, MAXPATHLEN) == TRUE
331*43a90889SApple OSS Distributions 	    || PE_parse_boot_argn("rootpath", root_path, MAXPATHLEN) == TRUE) {
332*43a90889SApple OSS Distributions 		if (imageboot_format_is_valid(root_path)) {
333*43a90889SApple OSS Distributions 			printf("netboot_info_init: rp0='%s' isn't a network path,"
334*43a90889SApple OSS Distributions 			    " ignoring\n", root_path);
335*43a90889SApple OSS Distributions 		} else {
336*43a90889SApple OSS Distributions 			have_root_path = TRUE;
337*43a90889SApple OSS Distributions 		}
338*43a90889SApple OSS Distributions 	}
339*43a90889SApple OSS Distributions 	if (have_root_path == FALSE) {
340*43a90889SApple OSS Distributions 		have_root_path = get_root_path(root_path);
341*43a90889SApple OSS Distributions 	}
342*43a90889SApple OSS Distributions 	if (have_root_path) {
343*43a90889SApple OSS Distributions 		const char * server_name = NULL;
344*43a90889SApple OSS Distributions 		char * mount_point = NULL;
345*43a90889SApple OSS Distributions 		char * image_path = NULL;
346*43a90889SApple OSS Distributions 		struct in_addr  server_ip;
347*43a90889SApple OSS Distributions 
348*43a90889SApple OSS Distributions 		if (parse_image_path(root_path, &server_ip, &server_name,
349*43a90889SApple OSS Distributions 		    &mount_point, &image_path)) {
350*43a90889SApple OSS Distributions 			/* kNetBootImageTypeNFS is deprecated */
351*43a90889SApple OSS Distributions 			printf("netboot: NFS boot is deprecated\n");
352*43a90889SApple OSS Distributions 		} else if (strncmp(root_path, kNetBootRootPathPrefixHTTP,
353*43a90889SApple OSS Distributions 		    strlen(kNetBootRootPathPrefixHTTP)) == 0) {
354*43a90889SApple OSS Distributions 			info->image_type = kNetBootImageTypeHTTP;
355*43a90889SApple OSS Distributions 			save_path(&info->image_path, &info->image_path_length,
356*43a90889SApple OSS Distributions 			    root_path);
357*43a90889SApple OSS Distributions 			printf("netboot: HTTP URL %s\n", info->image_path);
358*43a90889SApple OSS Distributions 		} else {
359*43a90889SApple OSS Distributions 			printf("netboot: root path uses unrecognized format\n");
360*43a90889SApple OSS Distributions 		}
361*43a90889SApple OSS Distributions 
362*43a90889SApple OSS Distributions 		/* check for image-within-image */
363*43a90889SApple OSS Distributions 		if (info->image_path != NULL) {
364*43a90889SApple OSS Distributions 			if (PE_parse_boot_argn(IMAGEBOOT_ROOT_ARG, root_path, MAXPATHLEN)
365*43a90889SApple OSS Distributions 			    || PE_parse_boot_argn("rp1", root_path, MAXPATHLEN)) {
366*43a90889SApple OSS Distributions 				/* rp1/root-dmg is the second-level image */
367*43a90889SApple OSS Distributions 				save_path(&info->second_image_path, &info->second_image_path_length,
368*43a90889SApple OSS Distributions 				    root_path);
369*43a90889SApple OSS Distributions 			}
370*43a90889SApple OSS Distributions 		}
371*43a90889SApple OSS Distributions 		if (info->second_image_path != NULL) {
372*43a90889SApple OSS Distributions 			printf("netboot: nested image %s\n", info->second_image_path);
373*43a90889SApple OSS Distributions 		}
374*43a90889SApple OSS Distributions 	}
375*43a90889SApple OSS Distributions 	zfree(ZV_NAMEI, root_path);
376*43a90889SApple OSS Distributions 	return info;
377*43a90889SApple OSS Distributions }
378*43a90889SApple OSS Distributions 
379*43a90889SApple OSS Distributions static void
netboot_info_free(struct netboot_info ** info_p)380*43a90889SApple OSS Distributions netboot_info_free(struct netboot_info * * info_p)
381*43a90889SApple OSS Distributions {
382*43a90889SApple OSS Distributions 	struct netboot_info * info = *info_p;
383*43a90889SApple OSS Distributions 
384*43a90889SApple OSS Distributions 	if (info) {
385*43a90889SApple OSS Distributions 		kfree_data(info->mount_point, info->mount_point_length);
386*43a90889SApple OSS Distributions 		kfree_data(info->server_name, info->server_name_length);
387*43a90889SApple OSS Distributions 		kfree_data(info->image_path, info->image_path_length);
388*43a90889SApple OSS Distributions 		kfree_data(info->second_image_path,
389*43a90889SApple OSS Distributions 		    info->second_image_path_length);
390*43a90889SApple OSS Distributions 		kfree_type(struct netboot_info, info);
391*43a90889SApple OSS Distributions 	}
392*43a90889SApple OSS Distributions 	*info_p = NULL;
393*43a90889SApple OSS Distributions }
394*43a90889SApple OSS Distributions 
395*43a90889SApple OSS Distributions boolean_t
netboot_iaddr(struct in_addr * iaddr_p)396*43a90889SApple OSS Distributions netboot_iaddr(struct in_addr * iaddr_p)
397*43a90889SApple OSS Distributions {
398*43a90889SApple OSS Distributions 	if (S_netboot_info_p == NULL) {
399*43a90889SApple OSS Distributions 		return FALSE;
400*43a90889SApple OSS Distributions 	}
401*43a90889SApple OSS Distributions 
402*43a90889SApple OSS Distributions 	*iaddr_p = S_netboot_info_p->client_ip;
403*43a90889SApple OSS Distributions 	return TRUE;
404*43a90889SApple OSS Distributions }
405*43a90889SApple OSS Distributions 
406*43a90889SApple OSS Distributions boolean_t
netboot_rootpath(struct in_addr * server_ip,char * name,size_t name_len,char * path,size_t path_len)407*43a90889SApple OSS Distributions netboot_rootpath(struct in_addr * server_ip,
408*43a90889SApple OSS Distributions     char * name, size_t name_len,
409*43a90889SApple OSS Distributions     char * path, size_t path_len)
410*43a90889SApple OSS Distributions {
411*43a90889SApple OSS Distributions 	if (S_netboot_info_p == NULL) {
412*43a90889SApple OSS Distributions 		return FALSE;
413*43a90889SApple OSS Distributions 	}
414*43a90889SApple OSS Distributions 
415*43a90889SApple OSS Distributions 	name[0] = '\0';
416*43a90889SApple OSS Distributions 	path[0] = '\0';
417*43a90889SApple OSS Distributions 
418*43a90889SApple OSS Distributions 	if (S_netboot_info_p->mount_point_length == 0) {
419*43a90889SApple OSS Distributions 		return FALSE;
420*43a90889SApple OSS Distributions 	}
421*43a90889SApple OSS Distributions 	if (path_len < S_netboot_info_p->mount_point_length) {
422*43a90889SApple OSS Distributions 		printf("netboot: path too small %zu < %zu\n",
423*43a90889SApple OSS Distributions 		    path_len, S_netboot_info_p->mount_point_length);
424*43a90889SApple OSS Distributions 		return FALSE;
425*43a90889SApple OSS Distributions 	}
426*43a90889SApple OSS Distributions 	strlcpy(path, S_netboot_info_p->mount_point, path_len);
427*43a90889SApple OSS Distributions 	strlcpy(name, S_netboot_info_p->server_name, name_len);
428*43a90889SApple OSS Distributions 	*server_ip = S_netboot_info_p->server_ip;
429*43a90889SApple OSS Distributions 	return TRUE;
430*43a90889SApple OSS Distributions }
431*43a90889SApple OSS Distributions 
432*43a90889SApple OSS Distributions 
433*43a90889SApple OSS Distributions static boolean_t
get_ip_parameters(struct in_addr * iaddr_p,struct in_addr * netmask_p,struct in_addr * router_p)434*43a90889SApple OSS Distributions get_ip_parameters(struct in_addr * iaddr_p, struct in_addr * netmask_p,
435*43a90889SApple OSS Distributions     struct in_addr * router_p)
436*43a90889SApple OSS Distributions {
437*43a90889SApple OSS Distributions 	void *              entry;
438*43a90889SApple OSS Distributions 	const void *        pkt;
439*43a90889SApple OSS Distributions 	int                 pkt_len;
440*43a90889SApple OSS Distributions 
441*43a90889SApple OSS Distributions 
442*43a90889SApple OSS Distributions 	entry = IOBSDRegistryEntryForDeviceTree("/chosen");
443*43a90889SApple OSS Distributions 	if (entry == NULL) {
444*43a90889SApple OSS Distributions 		return FALSE;
445*43a90889SApple OSS Distributions 	}
446*43a90889SApple OSS Distributions 	pkt = IOBSDRegistryEntryGetData(entry, DHCP_RESPONSE, &pkt_len);
447*43a90889SApple OSS Distributions 	if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
448*43a90889SApple OSS Distributions 		printf("netboot: retrieving IP information from DHCP response\n");
449*43a90889SApple OSS Distributions 	} else {
450*43a90889SApple OSS Distributions 		pkt = IOBSDRegistryEntryGetData(entry, BOOTP_RESPONSE, &pkt_len);
451*43a90889SApple OSS Distributions 		if (pkt != NULL && pkt_len >= (int)sizeof(struct dhcp)) {
452*43a90889SApple OSS Distributions 			printf("netboot: retrieving IP information from BOOTP response\n");
453*43a90889SApple OSS Distributions 		}
454*43a90889SApple OSS Distributions 	}
455*43a90889SApple OSS Distributions 	if (pkt != NULL) {
456*43a90889SApple OSS Distributions 		const struct in_addr *  ip;
457*43a90889SApple OSS Distributions 		int                     len;
458*43a90889SApple OSS Distributions 		dhcpol_t                options;
459*43a90889SApple OSS Distributions 		const struct dhcp *     reply;
460*43a90889SApple OSS Distributions 
461*43a90889SApple OSS Distributions 		reply = (const struct dhcp *)pkt;
462*43a90889SApple OSS Distributions 		(void)dhcpol_parse_packet(&options, reply, pkt_len);
463*43a90889SApple OSS Distributions 		*iaddr_p = reply->dp_yiaddr;
464*43a90889SApple OSS Distributions 		ip = (const struct in_addr *)
465*43a90889SApple OSS Distributions 		    dhcpol_find(&options,
466*43a90889SApple OSS Distributions 		    dhcptag_subnet_mask_e, &len, NULL);
467*43a90889SApple OSS Distributions 		if (ip) {
468*43a90889SApple OSS Distributions 			*netmask_p = *ip;
469*43a90889SApple OSS Distributions 		}
470*43a90889SApple OSS Distributions 		ip = (const struct in_addr *)
471*43a90889SApple OSS Distributions 		    dhcpol_find(&options, dhcptag_router_e, &len, NULL);
472*43a90889SApple OSS Distributions 		if (ip) {
473*43a90889SApple OSS Distributions 			*router_p = *ip;
474*43a90889SApple OSS Distributions 		}
475*43a90889SApple OSS Distributions 	}
476*43a90889SApple OSS Distributions 	IOBSDRegistryEntryRelease(entry);
477*43a90889SApple OSS Distributions 	return pkt != NULL;
478*43a90889SApple OSS Distributions }
479*43a90889SApple OSS Distributions 
480*43a90889SApple OSS Distributions static int
route_cmd(int cmd,struct in_addr d,struct in_addr g,struct in_addr m,uint32_t more_flags,unsigned int ifscope)481*43a90889SApple OSS Distributions route_cmd(int cmd, struct in_addr d, struct in_addr g,
482*43a90889SApple OSS Distributions     struct in_addr m, uint32_t more_flags, unsigned int ifscope)
483*43a90889SApple OSS Distributions {
484*43a90889SApple OSS Distributions 	struct sockaddr_in          dst;
485*43a90889SApple OSS Distributions 	int                         error;
486*43a90889SApple OSS Distributions 	uint32_t                    flags = RTF_UP | RTF_STATIC;
487*43a90889SApple OSS Distributions 	struct sockaddr_in          gw;
488*43a90889SApple OSS Distributions 	struct sockaddr_in          mask;
489*43a90889SApple OSS Distributions 
490*43a90889SApple OSS Distributions 	flags |= more_flags;
491*43a90889SApple OSS Distributions 
492*43a90889SApple OSS Distributions 	/* destination */
493*43a90889SApple OSS Distributions 	bzero((caddr_t)&dst, sizeof(dst));
494*43a90889SApple OSS Distributions 	dst.sin_len = sizeof(dst);
495*43a90889SApple OSS Distributions 	dst.sin_family = AF_INET;
496*43a90889SApple OSS Distributions 	dst.sin_addr = d;
497*43a90889SApple OSS Distributions 
498*43a90889SApple OSS Distributions 	/* gateway */
499*43a90889SApple OSS Distributions 	bzero((caddr_t)&gw, sizeof(gw));
500*43a90889SApple OSS Distributions 	gw.sin_len = sizeof(gw);
501*43a90889SApple OSS Distributions 	gw.sin_family = AF_INET;
502*43a90889SApple OSS Distributions 	gw.sin_addr = g;
503*43a90889SApple OSS Distributions 
504*43a90889SApple OSS Distributions 	/* mask */
505*43a90889SApple OSS Distributions 	bzero(&mask, sizeof(mask));
506*43a90889SApple OSS Distributions 	mask.sin_len = sizeof(mask);
507*43a90889SApple OSS Distributions 	mask.sin_family = AF_INET;
508*43a90889SApple OSS Distributions 	mask.sin_addr = m;
509*43a90889SApple OSS Distributions 
510*43a90889SApple OSS Distributions 	error = rtrequest_scoped(cmd, (struct sockaddr *)&dst,
511*43a90889SApple OSS Distributions 	    (struct sockaddr *)&gw, (struct sockaddr *)&mask, flags, NULL, ifscope);
512*43a90889SApple OSS Distributions 
513*43a90889SApple OSS Distributions 	return error;
514*43a90889SApple OSS Distributions }
515*43a90889SApple OSS Distributions 
516*43a90889SApple OSS Distributions static int
default_route_add(struct in_addr router,boolean_t proxy_arp)517*43a90889SApple OSS Distributions default_route_add(struct in_addr router, boolean_t proxy_arp)
518*43a90889SApple OSS Distributions {
519*43a90889SApple OSS Distributions 	uint32_t                    flags = 0;
520*43a90889SApple OSS Distributions 	struct in_addr              zeroes = { .s_addr = 0 };
521*43a90889SApple OSS Distributions 
522*43a90889SApple OSS Distributions 	if (proxy_arp == FALSE) {
523*43a90889SApple OSS Distributions 		flags |= RTF_GATEWAY;
524*43a90889SApple OSS Distributions 	}
525*43a90889SApple OSS Distributions 	return route_cmd(RTM_ADD, zeroes, router, zeroes, flags, IFSCOPE_NONE);
526*43a90889SApple OSS Distributions }
527*43a90889SApple OSS Distributions 
528*43a90889SApple OSS Distributions static struct ifnet *
find_interface(void)529*43a90889SApple OSS Distributions find_interface(void)
530*43a90889SApple OSS Distributions {
531*43a90889SApple OSS Distributions 	struct ifnet *              ifp = NULL;
532*43a90889SApple OSS Distributions 
533*43a90889SApple OSS Distributions 	dlil_if_lock();
534*43a90889SApple OSS Distributions 	if (rootdevice[0]) {
535*43a90889SApple OSS Distributions 		ifp = ifunit((char *)rootdevice);
536*43a90889SApple OSS Distributions 	}
537*43a90889SApple OSS Distributions 	if (ifp == NULL) {
538*43a90889SApple OSS Distributions 		ifnet_head_lock_shared();
539*43a90889SApple OSS Distributions 		TAILQ_FOREACH(ifp, &ifnet_head, if_link)
540*43a90889SApple OSS Distributions 		if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0) {
541*43a90889SApple OSS Distributions 			break;
542*43a90889SApple OSS Distributions 		}
543*43a90889SApple OSS Distributions 		ifnet_head_done();
544*43a90889SApple OSS Distributions 	}
545*43a90889SApple OSS Distributions 	dlil_if_unlock();
546*43a90889SApple OSS Distributions 	return ifp;
547*43a90889SApple OSS Distributions }
548*43a90889SApple OSS Distributions 
549*43a90889SApple OSS Distributions static const struct sockaddr_in blank_sin = {
550*43a90889SApple OSS Distributions 	.sin_len = sizeof(struct sockaddr_in),
551*43a90889SApple OSS Distributions 	.sin_family = AF_INET,
552*43a90889SApple OSS Distributions 	.sin_port = 0,
553*43a90889SApple OSS Distributions 	.sin_addr = { .s_addr = 0 },
554*43a90889SApple OSS Distributions 	.sin_zero = { 0, 0, 0, 0, 0, 0, 0, 0 }
555*43a90889SApple OSS Distributions };
556*43a90889SApple OSS Distributions 
557*43a90889SApple OSS Distributions static int
inet_aifaddr(struct socket * so,const char * name,const struct in_addr * addr,const struct in_addr * mask,const struct in_addr * broadcast)558*43a90889SApple OSS Distributions inet_aifaddr(struct socket * so, const char * name,
559*43a90889SApple OSS Distributions     const struct in_addr * addr,
560*43a90889SApple OSS Distributions     const struct in_addr * mask,
561*43a90889SApple OSS Distributions     const struct in_addr * broadcast)
562*43a90889SApple OSS Distributions {
563*43a90889SApple OSS Distributions 	struct ifaliasreq   ifra;
564*43a90889SApple OSS Distributions 
565*43a90889SApple OSS Distributions 	bzero(&ifra, sizeof(ifra));
566*43a90889SApple OSS Distributions 	strlcpy(ifra.ifra_name, name, sizeof(ifra.ifra_name));
567*43a90889SApple OSS Distributions 	if (addr) {
568*43a90889SApple OSS Distributions 		*((struct sockaddr_in *)(void *)&ifra.ifra_addr) = blank_sin;
569*43a90889SApple OSS Distributions 		((struct sockaddr_in *)(void *)&ifra.ifra_addr)->sin_addr = *addr;
570*43a90889SApple OSS Distributions 	}
571*43a90889SApple OSS Distributions 	if (mask) {
572*43a90889SApple OSS Distributions 		*((struct sockaddr_in *)(void *)&ifra.ifra_mask) = blank_sin;
573*43a90889SApple OSS Distributions 		((struct sockaddr_in *)(void *)&ifra.ifra_mask)->sin_addr = *mask;
574*43a90889SApple OSS Distributions 	}
575*43a90889SApple OSS Distributions 	if (broadcast) {
576*43a90889SApple OSS Distributions 		*((struct sockaddr_in *)(void *)&ifra.ifra_broadaddr) = blank_sin;
577*43a90889SApple OSS Distributions 		((struct sockaddr_in *)(void *)&ifra.ifra_broadaddr)->sin_addr = *broadcast;
578*43a90889SApple OSS Distributions 	}
579*43a90889SApple OSS Distributions 	return ifioctl(so, SIOCAIFADDR, (caddr_t)&ifra, current_proc());
580*43a90889SApple OSS Distributions }
581*43a90889SApple OSS Distributions 
582*43a90889SApple OSS Distributions 
583*43a90889SApple OSS Distributions int
netboot_mountroot(void)584*43a90889SApple OSS Distributions netboot_mountroot(void)
585*43a90889SApple OSS Distributions {
586*43a90889SApple OSS Distributions 	int                         error = 0;
587*43a90889SApple OSS Distributions 	struct in_addr              iaddr = { .s_addr = 0 };
588*43a90889SApple OSS Distributions 	struct ifreq                ifr;
589*43a90889SApple OSS Distributions 	struct ifnet *              ifp;
590*43a90889SApple OSS Distributions 	struct in_addr              netmask = { .s_addr = 0 };
591*43a90889SApple OSS Distributions 	proc_t                      procp = current_proc();
592*43a90889SApple OSS Distributions 	struct in_addr              router = { .s_addr = 0 };
593*43a90889SApple OSS Distributions 	struct socket *             so = NULL;
594*43a90889SApple OSS Distributions 
595*43a90889SApple OSS Distributions 	bzero(&ifr, sizeof(ifr));
596*43a90889SApple OSS Distributions 
597*43a90889SApple OSS Distributions 	/* find the interface */
598*43a90889SApple OSS Distributions 	ifp = find_interface();
599*43a90889SApple OSS Distributions 	if (ifp == NULL) {
600*43a90889SApple OSS Distributions 		printf("netboot: no suitable interface\n");
601*43a90889SApple OSS Distributions 		error = ENXIO;
602*43a90889SApple OSS Distributions 		goto failed;
603*43a90889SApple OSS Distributions 	}
604*43a90889SApple OSS Distributions 	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", if_name(ifp));
605*43a90889SApple OSS Distributions 	printf("netboot: using network interface '%s'\n", ifr.ifr_name);
606*43a90889SApple OSS Distributions 
607*43a90889SApple OSS Distributions 	/* bring it up */
608*43a90889SApple OSS Distributions 	if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)) != 0) {
609*43a90889SApple OSS Distributions 		printf("netboot: socreate, error=%d\n", error);
610*43a90889SApple OSS Distributions 		goto failed;
611*43a90889SApple OSS Distributions 	}
612*43a90889SApple OSS Distributions 	ifr.ifr_flags = ifp->if_flags | IFF_UP;
613*43a90889SApple OSS Distributions 	error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)&ifr, procp);
614*43a90889SApple OSS Distributions 	if (error) {
615*43a90889SApple OSS Distributions 		printf("netboot: SIFFLAGS, error=%d\n", error);
616*43a90889SApple OSS Distributions 		goto failed;
617*43a90889SApple OSS Distributions 	}
618*43a90889SApple OSS Distributions 
619*43a90889SApple OSS Distributions 	/* grab information from the registry */
620*43a90889SApple OSS Distributions 	if (get_ip_parameters(&iaddr, &netmask, &router) == FALSE) {
621*43a90889SApple OSS Distributions 		printf("netboot: can't retrieve IP parameters\n");
622*43a90889SApple OSS Distributions 		goto failed;
623*43a90889SApple OSS Distributions 	}
624*43a90889SApple OSS Distributions 	OS_ANALYZER_SUPPRESS("12641116") printf("netboot: IP address " IP_FORMAT, IP_LIST(&iaddr));
625*43a90889SApple OSS Distributions 	if (netmask.s_addr) {
626*43a90889SApple OSS Distributions 		printf(" netmask " IP_FORMAT, IP_LIST(&netmask));
627*43a90889SApple OSS Distributions 	}
628*43a90889SApple OSS Distributions 	if (router.s_addr) {
629*43a90889SApple OSS Distributions 		printf(" router " IP_FORMAT, IP_LIST(&router));
630*43a90889SApple OSS Distributions 	}
631*43a90889SApple OSS Distributions 	printf("\n");
632*43a90889SApple OSS Distributions 	error = inet_aifaddr(so, ifr.ifr_name, &iaddr, &netmask, NULL);
633*43a90889SApple OSS Distributions 	if (error) {
634*43a90889SApple OSS Distributions 		printf("netboot: inet_aifaddr failed, %d\n", error);
635*43a90889SApple OSS Distributions 		goto failed;
636*43a90889SApple OSS Distributions 	}
637*43a90889SApple OSS Distributions 	if (router.s_addr == 0) {
638*43a90889SApple OSS Distributions 		/* enable proxy arp if we don't have a router */
639*43a90889SApple OSS Distributions 		router.s_addr = iaddr.s_addr;
640*43a90889SApple OSS Distributions 	}
641*43a90889SApple OSS Distributions 	printf("netboot: adding default route " IP_FORMAT "\n",
642*43a90889SApple OSS Distributions 	    IP_LIST(&router));
643*43a90889SApple OSS Distributions 	error = default_route_add(router, router.s_addr == iaddr.s_addr);
644*43a90889SApple OSS Distributions 	if (error) {
645*43a90889SApple OSS Distributions 		printf("netboot: default_route_add failed %d\n", error);
646*43a90889SApple OSS Distributions 	}
647*43a90889SApple OSS Distributions 
648*43a90889SApple OSS Distributions 	soclose(so);
649*43a90889SApple OSS Distributions 
650*43a90889SApple OSS Distributions 	S_netboot_info_p = netboot_info_init(iaddr);
651*43a90889SApple OSS Distributions 	switch (S_netboot_info_p->image_type) {
652*43a90889SApple OSS Distributions 	default:
653*43a90889SApple OSS Distributions 	case kNetBootImageTypeNFS:
654*43a90889SApple OSS Distributions 		/* kNetBootImageTypeNFS is deprecated */
655*43a90889SApple OSS Distributions 		error = ENOTSUP;
656*43a90889SApple OSS Distributions 		break;
657*43a90889SApple OSS Distributions 	case kNetBootImageTypeHTTP:
658*43a90889SApple OSS Distributions 		error = netboot_setup();
659*43a90889SApple OSS Distributions 		break;
660*43a90889SApple OSS Distributions 	}
661*43a90889SApple OSS Distributions 	if (error == 0) {
662*43a90889SApple OSS Distributions 		S_netboot = 1;
663*43a90889SApple OSS Distributions 	} else {
664*43a90889SApple OSS Distributions 		S_netboot = 0;
665*43a90889SApple OSS Distributions 	}
666*43a90889SApple OSS Distributions 	return error;
667*43a90889SApple OSS Distributions failed:
668*43a90889SApple OSS Distributions 	if (so != NULL) {
669*43a90889SApple OSS Distributions 		soclose(so);
670*43a90889SApple OSS Distributions 	}
671*43a90889SApple OSS Distributions 	return error;
672*43a90889SApple OSS Distributions }
673*43a90889SApple OSS Distributions 
674*43a90889SApple OSS Distributions int
netboot_setup(void)675*43a90889SApple OSS Distributions netboot_setup(void)
676*43a90889SApple OSS Distributions {
677*43a90889SApple OSS Distributions 	int         error = 0;
678*43a90889SApple OSS Distributions 
679*43a90889SApple OSS Distributions 	if (S_netboot_info_p == NULL
680*43a90889SApple OSS Distributions 	    || S_netboot_info_p->image_path == NULL) {
681*43a90889SApple OSS Distributions 		goto done;
682*43a90889SApple OSS Distributions 	}
683*43a90889SApple OSS Distributions 	printf("netboot_setup: calling imageboot_mount_image\n");
684*43a90889SApple OSS Distributions 	error = imageboot_mount_image(S_netboot_info_p->image_path, -1, IMAGEBOOT_DMG);
685*43a90889SApple OSS Distributions 	if (error != 0) {
686*43a90889SApple OSS Distributions 		printf("netboot: failed to mount root image, %d\n", error);
687*43a90889SApple OSS Distributions 	} else if (S_netboot_info_p->second_image_path != NULL) {
688*43a90889SApple OSS Distributions 		error = imageboot_mount_image(S_netboot_info_p->second_image_path, 0, IMAGEBOOT_DMG);
689*43a90889SApple OSS Distributions 		if (error != 0) {
690*43a90889SApple OSS Distributions 			printf("netboot: failed to mount second root image, %d\n", error);
691*43a90889SApple OSS Distributions 		}
692*43a90889SApple OSS Distributions 	}
693*43a90889SApple OSS Distributions 
694*43a90889SApple OSS Distributions done:
695*43a90889SApple OSS Distributions 	netboot_info_free(&S_netboot_info_p);
696*43a90889SApple OSS Distributions 	return error;
697*43a90889SApple OSS Distributions }
698*43a90889SApple OSS Distributions 
699*43a90889SApple OSS Distributions int
netboot_root(void)700*43a90889SApple OSS Distributions netboot_root(void)
701*43a90889SApple OSS Distributions {
702*43a90889SApple OSS Distributions 	return S_netboot;
703*43a90889SApple OSS Distributions }
704