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