xref: /illumos-gate/usr/src/boot/common/dev_net.c (revision 22028508)
1f27dfbe1SToomas Soome /*
2199767f8SToomas Soome  * Copyright (c) 1997 The NetBSD Foundation, Inc.
3199767f8SToomas Soome  * All rights reserved.
4199767f8SToomas Soome  *
5199767f8SToomas Soome  * This code is derived from software contributed to The NetBSD Foundation
6199767f8SToomas Soome  * by Gordon W. Ross.
7199767f8SToomas Soome  *
8199767f8SToomas Soome  * Redistribution and use in source and binary forms, with or without
9199767f8SToomas Soome  * modification, are permitted provided that the following conditions
10199767f8SToomas Soome  * are met:
11199767f8SToomas Soome  * 1. Redistributions of source code must retain the above copyright
12199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer.
13199767f8SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
14199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
15199767f8SToomas Soome  *    documentation and/or other materials provided with the distribution.
16199767f8SToomas Soome  *
17199767f8SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18199767f8SToomas Soome  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19199767f8SToomas Soome  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20199767f8SToomas Soome  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21199767f8SToomas Soome  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22199767f8SToomas Soome  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23199767f8SToomas Soome  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24199767f8SToomas Soome  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25199767f8SToomas Soome  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26199767f8SToomas Soome  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27199767f8SToomas Soome  * POSSIBILITY OF SUCH DAMAGE.
28199767f8SToomas Soome  */
29199767f8SToomas Soome 
30924d84dcSAndy Fiddaman /*
31924d84dcSAndy Fiddaman  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
32924d84dcSAndy Fiddaman  */
33924d84dcSAndy Fiddaman 
34199767f8SToomas Soome #include <sys/cdefs.h>
35199767f8SToomas Soome 
36f27dfbe1SToomas Soome /*
37199767f8SToomas Soome  * This module implements a "raw device" interface suitable for
38199767f8SToomas Soome  * use by the stand-alone I/O library NFS code.  This interface
39199767f8SToomas Soome  * does not support any "block" access, and exists only for the
40199767f8SToomas Soome  * purpose of initializing the network interface, getting boot
41199767f8SToomas Soome  * parameters, and performing the NFS mount.
42199767f8SToomas Soome  *
43199767f8SToomas Soome  * At open time, this does:
44199767f8SToomas Soome  *
45199767f8SToomas Soome  * find interface      - netif_open()
46199767f8SToomas Soome  * RARP for IP address - rarp_getipaddress()
47199767f8SToomas Soome  * RPC/bootparams      - callrpc(d, RPC_BOOTPARAMS, ...)
48199767f8SToomas Soome  * RPC/mountd          - nfs_mount(sock, ip, path)
49199767f8SToomas Soome  *
50199767f8SToomas Soome  * the root file handle from mountd is saved in a global
51199767f8SToomas Soome  * for use by the NFS open code (NFS/lookup).
52199767f8SToomas Soome  */
53199767f8SToomas Soome 
54199767f8SToomas Soome #include <machine/stdarg.h>
55199767f8SToomas Soome #include <sys/param.h>
56199767f8SToomas Soome #include <sys/socket.h>
57199767f8SToomas Soome #include <net/if.h>
58199767f8SToomas Soome #include <netinet/in.h>
59199767f8SToomas Soome #include <netinet/in_systm.h>
60199767f8SToomas Soome 
61199767f8SToomas Soome #include <stand.h>
62859472daSToomas Soome #include <stddef.h>
63199767f8SToomas Soome #include <string.h>
64199767f8SToomas Soome #include <net.h>
65199767f8SToomas Soome #include <netif.h>
66199767f8SToomas Soome #include <bootp.h>
67199767f8SToomas Soome #include <bootparam.h>
68199767f8SToomas Soome 
69199767f8SToomas Soome #include "dev_net.h"
70199767f8SToomas Soome #include "bootstrap.h"
71199767f8SToomas Soome 
72199767f8SToomas Soome #ifdef	NETIF_DEBUG
73199767f8SToomas Soome int debug = 0;
74199767f8SToomas Soome #endif
75199767f8SToomas Soome 
76199767f8SToomas Soome static char *netdev_name;
77199767f8SToomas Soome static int netdev_sock = -1;
78199767f8SToomas Soome static int netdev_opens;
79199767f8SToomas Soome 
80199767f8SToomas Soome static int	net_init(void);
81199767f8SToomas Soome static int	net_open(struct open_file *, ...);
82199767f8SToomas Soome static int	net_close(struct open_file *);
83199767f8SToomas Soome static void	net_cleanup(void);
84f27dfbe1SToomas Soome static int	net_strategy(void *, int, daddr_t, size_t, char *, size_t *);
85199767f8SToomas Soome static int	net_print(int);
86199767f8SToomas Soome 
87199767f8SToomas Soome static int net_getparams(int sock);
88199767f8SToomas Soome 
89199767f8SToomas Soome struct devsw netdev = {
90199767f8SToomas Soome 	"net",
91199767f8SToomas Soome 	DEVT_NET,
92199767f8SToomas Soome 	net_init,
93199767f8SToomas Soome 	net_strategy,
94199767f8SToomas Soome 	net_open,
95199767f8SToomas Soome 	net_close,
96199767f8SToomas Soome 	noioctl,
97199767f8SToomas Soome 	net_print,
98199767f8SToomas Soome 	net_cleanup
99199767f8SToomas Soome };
100199767f8SToomas Soome 
101f27dfbe1SToomas Soome static struct uri_scheme {
102f27dfbe1SToomas Soome 	const char *scheme;
103f27dfbe1SToomas Soome 	int proto;
104f27dfbe1SToomas Soome } uri_schemes[] = {
105f27dfbe1SToomas Soome 	{ "tftp:/", NET_TFTP },
106f27dfbe1SToomas Soome 	{ "nfs:/", NET_NFS },
107f27dfbe1SToomas Soome };
108f27dfbe1SToomas Soome 
109199767f8SToomas Soome static int
net_init(void)110199767f8SToomas Soome net_init(void)
111199767f8SToomas Soome {
112199767f8SToomas Soome 
113199767f8SToomas Soome 	return (0);
114199767f8SToomas Soome }
115199767f8SToomas Soome 
116199767f8SToomas Soome /*
117199767f8SToomas Soome  * Called by devopen after it sets f->f_dev to our devsw entry.
1186538c7b4SToomas Soome  * This opens the low-level device and sets dev->d_opendata.
119199767f8SToomas Soome  * This is declared with variable arguments...
120199767f8SToomas Soome  */
121199767f8SToomas Soome static int
net_open(struct open_file * f,...)122199767f8SToomas Soome net_open(struct open_file *f, ...)
123199767f8SToomas Soome {
124199767f8SToomas Soome 	struct iodesc *d;
125199767f8SToomas Soome 	va_list args;
126ca4fa6c7SToomas Soome 	struct devdesc *dev;
127ca4fa6c7SToomas Soome 	const char *devname;	/* Device part of file name (or NULL). */
128199767f8SToomas Soome 	int error = 0;
129199767f8SToomas Soome 
130199767f8SToomas Soome 	va_start(args, f);
131ca4fa6c7SToomas Soome 	dev = va_arg(args, struct devdesc *);
132199767f8SToomas Soome 	va_end(args);
133199767f8SToomas Soome 
134ca4fa6c7SToomas Soome 	devname = dev->d_dev->dv_name;
135199767f8SToomas Soome 	/* Before opening another interface, close the previous one first. */
136199767f8SToomas Soome 	if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0)
137199767f8SToomas Soome 		net_cleanup();
138199767f8SToomas Soome 
139199767f8SToomas Soome 	/* On first open, do netif open, mount, etc. */
140199767f8SToomas Soome 	if (netdev_opens == 0) {
141199767f8SToomas Soome 		/* Find network interface. */
142199767f8SToomas Soome 		if (netdev_sock < 0) {
143ca4fa6c7SToomas Soome 			netdev_sock = netif_open(dev);
144199767f8SToomas Soome 			if (netdev_sock < 0) {
14546baa6ffSToomas Soome 				printf("%s: netif_open() failed\n", __func__);
146199767f8SToomas Soome 				return (ENXIO);
147199767f8SToomas Soome 			}
148199767f8SToomas Soome 			netdev_name = strdup(devname);
149199767f8SToomas Soome #ifdef	NETIF_DEBUG
150199767f8SToomas Soome 			if (debug)
15146baa6ffSToomas Soome 				printf("%s: netif_open() succeeded\n",
15246baa6ffSToomas Soome 				    __func__);
153199767f8SToomas Soome #endif
154199767f8SToomas Soome 		}
155199767f8SToomas Soome 		/*
156199767f8SToomas Soome 		 * If network params were not set by netif_open(), try to get
157199767f8SToomas Soome 		 * them via bootp, rarp, etc.
158199767f8SToomas Soome 		 */
159199767f8SToomas Soome 		if (rootip.s_addr == 0) {
160199767f8SToomas Soome 			/* Get root IP address, and path, etc. */
161199767f8SToomas Soome 			error = net_getparams(netdev_sock);
162199767f8SToomas Soome 			if (error) {
163199767f8SToomas Soome 				/* getparams makes its own noise */
164199767f8SToomas Soome 				free(netdev_name);
165199767f8SToomas Soome 				netif_close(netdev_sock);
166199767f8SToomas Soome 				netdev_sock = -1;
167199767f8SToomas Soome 				return (error);
168199767f8SToomas Soome 			}
169199767f8SToomas Soome 		}
170199767f8SToomas Soome 		/*
171199767f8SToomas Soome 		 * Set the variables required by the kernel's nfs_diskless
172199767f8SToomas Soome 		 * mechanism.  This is the minimum set of variables required to
173199767f8SToomas Soome 		 * mount a root filesystem without needing to obtain additional
174199767f8SToomas Soome 		 * info from bootp or other sources.
175199767f8SToomas Soome 		 */
176199767f8SToomas Soome 		d = socktodesc(netdev_sock);
177199767f8SToomas Soome 		setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 1);
178199767f8SToomas Soome 		setenv("boot.netif.ip", inet_ntoa(myip), 1);
179199767f8SToomas Soome 		setenv("boot.netif.netmask", intoa(netmask), 1);
180199767f8SToomas Soome 		setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
181aa61755eSToomas Soome 		setenv("boot.netif.server", inet_ntoa(rootip), 1);
182aa61755eSToomas Soome 		if (netproto == NET_TFTP) {
183aa61755eSToomas Soome 			setenv("boot.tftproot.server", inet_ntoa(rootip), 1);
184aa61755eSToomas Soome 			setenv("boot.tftproot.path", rootpath, 1);
185aa61755eSToomas Soome 		} else {
186aa61755eSToomas Soome 			setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
187aa61755eSToomas Soome 			setenv("boot.nfsroot.path", rootpath, 1);
188aa61755eSToomas Soome 		}
189c21cf554SToomas Soome 		if (intf_mtu != 0) {
190c21cf554SToomas Soome 			char mtu[16];
191f27dfbe1SToomas Soome 			snprintf(mtu, sizeof (mtu), "%u", intf_mtu);
192c21cf554SToomas Soome 			setenv("boot.netif.mtu", mtu, 1);
193c21cf554SToomas Soome 		}
194199767f8SToomas Soome 	}
195199767f8SToomas Soome 	netdev_opens++;
1966538c7b4SToomas Soome 	dev->d_opendata = &netdev_sock;
197199767f8SToomas Soome 	return (error);
198199767f8SToomas Soome }
199199767f8SToomas Soome 
200199767f8SToomas Soome static int
net_close(struct open_file * f)201199767f8SToomas Soome net_close(struct open_file *f)
202199767f8SToomas Soome {
2036538c7b4SToomas Soome 	struct devdesc *dev;
204199767f8SToomas Soome 
205199767f8SToomas Soome #ifdef	NETIF_DEBUG
206199767f8SToomas Soome 	if (debug)
20746baa6ffSToomas Soome 		printf("%s: opens=%d\n", __func__, netdev_opens);
208199767f8SToomas Soome #endif
209199767f8SToomas Soome 
2106538c7b4SToomas Soome 	dev = f->f_devdata;
2116538c7b4SToomas Soome 	dev->d_opendata = NULL;
212199767f8SToomas Soome 
213199767f8SToomas Soome 	return (0);
214199767f8SToomas Soome }
215199767f8SToomas Soome 
216199767f8SToomas Soome static void
net_cleanup(void)217199767f8SToomas Soome net_cleanup(void)
218199767f8SToomas Soome {
219199767f8SToomas Soome 
220199767f8SToomas Soome 	if (netdev_sock >= 0) {
221199767f8SToomas Soome #ifdef	NETIF_DEBUG
222199767f8SToomas Soome 		if (debug)
22346baa6ffSToomas Soome 			printf("%s: calling netif_close()\n", __func__);
224199767f8SToomas Soome #endif
225199767f8SToomas Soome 		rootip.s_addr = 0;
226199767f8SToomas Soome 		free(netdev_name);
227199767f8SToomas Soome 		netif_close(netdev_sock);
228199767f8SToomas Soome 		netdev_sock = -1;
229199767f8SToomas Soome 	}
230199767f8SToomas Soome }
231199767f8SToomas Soome 
232199767f8SToomas Soome static int
net_strategy(void * devdata __unused,int rw __unused,daddr_t blk __unused,size_t size __unused,char * buf __unused,size_t * rsize __unused)2338eef2ab6SToomas Soome net_strategy(void *devdata __unused, int rw __unused, daddr_t blk __unused,
2348eef2ab6SToomas Soome     size_t size __unused, char *buf __unused, size_t *rsize __unused)
235199767f8SToomas Soome {
236199767f8SToomas Soome 
237199767f8SToomas Soome 	return (EIO);
238199767f8SToomas Soome }
239199767f8SToomas Soome 
240199767f8SToomas Soome /*
241199767f8SToomas Soome  * Get info for NFS boot: our IP address, our hostname,
242199767f8SToomas Soome  * server IP address, and our root path on the server.
243199767f8SToomas Soome  * There are two ways to do this:  The old, Sun way,
244ff6ae1f7SToomas Soome  * and the more modern, BOOTP/DHCP way. (RFC951, RFC1048)
245199767f8SToomas Soome  */
246199767f8SToomas Soome 
247199767f8SToomas Soome extern n_long ip_convertaddr(char *p);
248199767f8SToomas Soome 
249199767f8SToomas Soome static int
net_getparams(int sock)250199767f8SToomas Soome net_getparams(int sock)
251199767f8SToomas Soome {
252199767f8SToomas Soome 	char buf[MAXHOSTNAMELEN];
253199767f8SToomas Soome 	n_long rootaddr, smask;
254199767f8SToomas Soome 
255199767f8SToomas Soome 	/*
256ff6ae1f7SToomas Soome 	 * Try to get boot info using BOOTP/DHCP.  If we succeed, then
257199767f8SToomas Soome 	 * the server IP address, gateway, and root path will all
258199767f8SToomas Soome 	 * be initialized.  If any remain uninitialized, we will
259199767f8SToomas Soome 	 * use RARP and RPC/bootparam (the Sun way) to get them.
260199767f8SToomas Soome 	 */
261ff6ae1f7SToomas Soome 	bootp(sock);
262199767f8SToomas Soome 	if (myip.s_addr != 0)
263199767f8SToomas Soome 		goto exit;
264199767f8SToomas Soome #ifdef	NETIF_DEBUG
265199767f8SToomas Soome 	if (debug)
26646baa6ffSToomas Soome 		printf("%s: BOOTP failed, trying RARP/RPC...\n", __func__);
267199767f8SToomas Soome #endif
268199767f8SToomas Soome 
269199767f8SToomas Soome 	/*
270199767f8SToomas Soome 	 * Use RARP to get our IP address.  This also sets our
271199767f8SToomas Soome 	 * netmask to the "natural" default for our address.
272199767f8SToomas Soome 	 */
273199767f8SToomas Soome 	if (rarp_getipaddress(sock)) {
27446baa6ffSToomas Soome 		printf("%s: RARP failed\n", __func__);
275199767f8SToomas Soome 		return (EIO);
276199767f8SToomas Soome 	}
27746baa6ffSToomas Soome 	printf("%s: client addr: %s\n", __func__, inet_ntoa(myip));
278199767f8SToomas Soome 
279199767f8SToomas Soome 	/* Get our hostname, server IP address, gateway. */
280199767f8SToomas Soome 	if (bp_whoami(sock)) {
28146baa6ffSToomas Soome 		printf("%s: bootparam/whoami RPC failed\n", __func__);
282199767f8SToomas Soome 		return (EIO);
283199767f8SToomas Soome 	}
284199767f8SToomas Soome #ifdef	NETIF_DEBUG
285199767f8SToomas Soome 	if (debug)
28646baa6ffSToomas Soome 		printf("%s: client name: %s\n", __func__, hostname);
287199767f8SToomas Soome #endif
288199767f8SToomas Soome 
289199767f8SToomas Soome 	/*
290199767f8SToomas Soome 	 * Ignore the gateway from whoami (unreliable).
291199767f8SToomas Soome 	 * Use the "gateway" parameter instead.
292199767f8SToomas Soome 	 */
293199767f8SToomas Soome 	smask = 0;
294199767f8SToomas Soome 	gateip.s_addr = 0;
295199767f8SToomas Soome 	if (bp_getfile(sock, "gateway", &gateip, buf) == 0) {
296199767f8SToomas Soome 		/* Got it!  Parse the netmask. */
297199767f8SToomas Soome 		smask = ip_convertaddr(buf);
298199767f8SToomas Soome 	}
299199767f8SToomas Soome 	if (smask) {
300199767f8SToomas Soome 		netmask = smask;
301199767f8SToomas Soome #ifdef	NETIF_DEBUG
302199767f8SToomas Soome 		if (debug)
30346baa6ffSToomas Soome 			printf("%s: subnet mask: %s\n", __func__,
30446baa6ffSToomas Soome 			    intoa(netmask));
305199767f8SToomas Soome #endif
306199767f8SToomas Soome 	}
307199767f8SToomas Soome #ifdef	NETIF_DEBUG
308199767f8SToomas Soome 	if (gateip.s_addr && debug)
30946baa6ffSToomas Soome 		printf("%s: net gateway: %s\n", __func__, inet_ntoa(gateip));
310199767f8SToomas Soome #endif
311199767f8SToomas Soome 
312199767f8SToomas Soome 	/* Get the root server and pathname. */
313199767f8SToomas Soome 	if (bp_getfile(sock, "root", &rootip, rootpath)) {
31446baa6ffSToomas Soome 		printf("%s: bootparam/getfile RPC failed\n", __func__);
315199767f8SToomas Soome 		return (EIO);
316199767f8SToomas Soome 	}
317199767f8SToomas Soome exit:
318f27dfbe1SToomas Soome 	if ((rootaddr = net_parse_rootpath()) != INADDR_NONE)
319199767f8SToomas Soome 		rootip.s_addr = rootaddr;
320199767f8SToomas Soome 
321199767f8SToomas Soome #ifdef	NETIF_DEBUG
322199767f8SToomas Soome 	if (debug) {
32346baa6ffSToomas Soome 		printf("%s: server addr: %s\n", __func__,
32446baa6ffSToomas Soome 		    inet_ntoa(rootip));
32546baa6ffSToomas Soome 		printf("%s: server path: %s\n", __func__, rootpath);
326199767f8SToomas Soome 	}
327199767f8SToomas Soome #endif
328199767f8SToomas Soome 
329199767f8SToomas Soome 	return (0);
330199767f8SToomas Soome }
331199767f8SToomas Soome 
332199767f8SToomas Soome static int
net_print(int verbose)333199767f8SToomas Soome net_print(int verbose)
334199767f8SToomas Soome {
335199767f8SToomas Soome 	struct netif_driver *drv;
336199767f8SToomas Soome 	int i, d, cnt;
337199767f8SToomas Soome 	int ret = 0;
338199767f8SToomas Soome 
339502b33a5SToomas Soome 	if (netif_drivers[0] == NULL)
340502b33a5SToomas Soome 		return (ret);
341502b33a5SToomas Soome 
342502b33a5SToomas Soome 	printf("%s devices:", netdev.dv_name);
343502b33a5SToomas Soome 	if ((ret = pager_output("\n")) != 0)
344502b33a5SToomas Soome 		return (ret);
345502b33a5SToomas Soome 
346199767f8SToomas Soome 	cnt = 0;
347199767f8SToomas Soome 	for (d = 0; netif_drivers[d]; d++) {
348199767f8SToomas Soome 		drv = netif_drivers[d];
349199767f8SToomas Soome 		for (i = 0; i < drv->netif_nifs; i++) {
350502b33a5SToomas Soome 			printf("\t%s%d:", netdev.dv_name, cnt++);
351199767f8SToomas Soome 			if (verbose) {
352502b33a5SToomas Soome 				printf(" (%s%d)", drv->netif_bname,
353199767f8SToomas Soome 				    drv->netif_ifs[i].dif_unit);
354199767f8SToomas Soome 			}
355502b33a5SToomas Soome 			if ((ret = pager_output("\n")) != 0)
356502b33a5SToomas Soome 				return (ret);
357199767f8SToomas Soome 		}
358199767f8SToomas Soome 	}
359502b33a5SToomas Soome 	return (ret);
360199767f8SToomas Soome }
361199767f8SToomas Soome 
362199767f8SToomas Soome /*
363f27dfbe1SToomas Soome  * Parses the rootpath if present
364f27dfbe1SToomas Soome  *
365f27dfbe1SToomas Soome  * The rootpath format can be in the form
366f27dfbe1SToomas Soome  * <scheme>://IPv4/path
367f27dfbe1SToomas Soome  * <scheme>:/path
368f27dfbe1SToomas Soome  *
369f27dfbe1SToomas Soome  * For compatibility with previous behaviour it also accepts as an NFS scheme
370f27dfbe1SToomas Soome  * IPv4:/path
371f27dfbe1SToomas Soome  * /path
372f27dfbe1SToomas Soome  *
373f27dfbe1SToomas Soome  * If an IPv4 address has been specified, it will be stripped out and passed
374f27dfbe1SToomas Soome  * out as the return value of this function in network byte order.
375f27dfbe1SToomas Soome  *
376924d84dcSAndy Fiddaman  * If no rootpath is present then we will default to TFTP.
377924d84dcSAndy Fiddaman  *
378f27dfbe1SToomas Soome  * If no global default scheme has been specified and no scheme has been
379f27dfbe1SToomas Soome  * specified, we will assume that this is an NFS URL.
380f27dfbe1SToomas Soome  *
381f27dfbe1SToomas Soome  * The pathname will be stored in the global variable rootpath.
382199767f8SToomas Soome  */
383199767f8SToomas Soome uint32_t
net_parse_rootpath(void)384f27dfbe1SToomas Soome net_parse_rootpath(void)
385199767f8SToomas Soome {
386f27dfbe1SToomas Soome 	n_long addr = htonl(INADDR_NONE);
387f27dfbe1SToomas Soome 	size_t i;
388f27dfbe1SToomas Soome 	char ip[FNAME_SIZE];
389f27dfbe1SToomas Soome 	char *ptr, *val;
390f27dfbe1SToomas Soome 
391f27dfbe1SToomas Soome 	netproto = NET_NONE;
392f27dfbe1SToomas Soome 
393f27dfbe1SToomas Soome 	for (i = 0; i < nitems(uri_schemes); i++) {
394f27dfbe1SToomas Soome 		if (strncmp(rootpath, uri_schemes[i].scheme,
395f27dfbe1SToomas Soome 		    strlen(uri_schemes[i].scheme)) != 0)
396f27dfbe1SToomas Soome 			continue;
397199767f8SToomas Soome 
398f27dfbe1SToomas Soome 		netproto = uri_schemes[i].proto;
399f27dfbe1SToomas Soome 		break;
400f27dfbe1SToomas Soome 	}
40181868483SToomas Soome 	ptr = rootpath;
402f27dfbe1SToomas Soome 	/* Fallback for compatibility mode */
403f27dfbe1SToomas Soome 	if (netproto == NET_NONE) {
404924d84dcSAndy Fiddaman 		if (strcmp(rootpath, "/") == 0) {
405924d84dcSAndy Fiddaman 			netproto = NET_TFTP;
406924d84dcSAndy Fiddaman 		} else {
407924d84dcSAndy Fiddaman 			netproto = NET_NFS;
408924d84dcSAndy Fiddaman 			(void) strsep(&ptr, ":");
409924d84dcSAndy Fiddaman 			if (ptr != NULL) {
410924d84dcSAndy Fiddaman 				addr = inet_addr(rootpath);
411924d84dcSAndy Fiddaman 				bcopy(ptr, rootpath, strlen(ptr) + 1);
412924d84dcSAndy Fiddaman 			}
413f27dfbe1SToomas Soome 		}
414f27dfbe1SToomas Soome 	} else {
415f27dfbe1SToomas Soome 		ptr += strlen(uri_schemes[i].scheme);
416f27dfbe1SToomas Soome 		if (*ptr == '/') {
41746baa6ffSToomas Soome 			/*
41846baa6ffSToomas Soome 			 * We are in the form <scheme>://, we do expect an ip.
41946baa6ffSToomas Soome 			 */
420f27dfbe1SToomas Soome 			ptr++;
421f27dfbe1SToomas Soome 			/*
422f27dfbe1SToomas Soome 			 * XXX when http will be there we will need to check for
423f27dfbe1SToomas Soome 			 * a port, but right now we do not need it yet.
424f27dfbe1SToomas Soome 			 * Also will need rework for IPv6.
425f27dfbe1SToomas Soome 			 */
426f27dfbe1SToomas Soome 			val = strchr(ptr, '/');
427924d84dcSAndy Fiddaman 			if (val == NULL) {
428924d84dcSAndy Fiddaman 				/* If no pathname component, default to / */
429924d84dcSAndy Fiddaman 				strlcat(rootpath, "/", sizeof (rootpath));
430924d84dcSAndy Fiddaman 				val = strchr(ptr, '/');
431924d84dcSAndy Fiddaman 			}
432f27dfbe1SToomas Soome 			if (val != NULL) {
433f27dfbe1SToomas Soome 				snprintf(ip, sizeof (ip), "%.*s",
434f27dfbe1SToomas Soome 				    (int)((uintptr_t)val - (uintptr_t)ptr),
435f27dfbe1SToomas Soome 				    ptr);
436f27dfbe1SToomas Soome 				addr = inet_addr(ip);
437f27dfbe1SToomas Soome 				if (addr == htonl(INADDR_NONE)) {
438f27dfbe1SToomas Soome 					printf("Bad IP address: %s\n", ip);
439f27dfbe1SToomas Soome 				}
440f27dfbe1SToomas Soome 				bcopy(val, rootpath, strlen(val) + 1);
441f27dfbe1SToomas Soome 			}
442f27dfbe1SToomas Soome 		} else {
443f27dfbe1SToomas Soome 			ptr--;
444f27dfbe1SToomas Soome 			bcopy(ptr, rootpath, strlen(ptr) + 1);
445f27dfbe1SToomas Soome 		}
446199767f8SToomas Soome 	}
447f27dfbe1SToomas Soome 
448199767f8SToomas Soome 	return (addr);
449199767f8SToomas Soome }
450