1ca987d46SWarner Losh /* $NetBSD: dev_net.c,v 1.23 2008/04/28 20:24:06 martin Exp $ */ 2ca987d46SWarner Losh 3ca987d46SWarner Losh /*- 4ca987d46SWarner Losh * Copyright (c) 1997 The NetBSD Foundation, Inc. 5ca987d46SWarner Losh * All rights reserved. 6ca987d46SWarner Losh * 7ca987d46SWarner Losh * This code is derived from software contributed to The NetBSD Foundation 8ca987d46SWarner Losh * by Gordon W. Ross. 9ca987d46SWarner Losh * 10ca987d46SWarner Losh * Redistribution and use in source and binary forms, with or without 11ca987d46SWarner Losh * modification, are permitted provided that the following conditions 12ca987d46SWarner Losh * are met: 13ca987d46SWarner Losh * 1. Redistributions of source code must retain the above copyright 14ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer. 15ca987d46SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 16ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer in the 17ca987d46SWarner Losh * documentation and/or other materials provided with the distribution. 18ca987d46SWarner Losh * 19ca987d46SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20ca987d46SWarner Losh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21ca987d46SWarner Losh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22ca987d46SWarner Losh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23ca987d46SWarner Losh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24ca987d46SWarner Losh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25ca987d46SWarner Losh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26ca987d46SWarner Losh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27ca987d46SWarner Losh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28ca987d46SWarner Losh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29ca987d46SWarner Losh * POSSIBILITY OF SUCH DAMAGE. 30ca987d46SWarner Losh */ 31ca987d46SWarner Losh 32ca987d46SWarner Losh #include <sys/cdefs.h> 33ca987d46SWarner Losh __FBSDID("$FreeBSD$"); 34ca987d46SWarner Losh 35ca987d46SWarner Losh /*- 36ca987d46SWarner Losh * This module implements a "raw device" interface suitable for 37ca987d46SWarner Losh * use by the stand-alone I/O library NFS code. This interface 38ca987d46SWarner Losh * does not support any "block" access, and exists only for the 39ca987d46SWarner Losh * purpose of initializing the network interface, getting boot 40ca987d46SWarner Losh * parameters, and performing the NFS mount. 41ca987d46SWarner Losh * 42ca987d46SWarner Losh * At open time, this does: 43ca987d46SWarner Losh * 44ca987d46SWarner Losh * find interface - netif_open() 45ca987d46SWarner Losh * RARP for IP address - rarp_getipaddress() 46ca987d46SWarner Losh * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) 47ca987d46SWarner Losh * RPC/mountd - nfs_mount(sock, ip, path) 48ca987d46SWarner Losh * 49ca987d46SWarner Losh * the root file handle from mountd is saved in a global 50ca987d46SWarner Losh * for use by the NFS open code (NFS/lookup). 51ca987d46SWarner Losh */ 52ca987d46SWarner Losh 53ca987d46SWarner Losh #include <machine/stdarg.h> 54ca987d46SWarner Losh #include <sys/param.h> 55ca987d46SWarner Losh #include <sys/socket.h> 56ca987d46SWarner Losh #include <net/if.h> 57ca987d46SWarner Losh #include <netinet/in.h> 58ca987d46SWarner Losh #include <netinet/in_systm.h> 59ca987d46SWarner Losh 60ca987d46SWarner Losh #include <stand.h> 61ca987d46SWarner Losh #include <stddef.h> 62ca987d46SWarner Losh #include <string.h> 63ca987d46SWarner Losh #include <net.h> 64ca987d46SWarner Losh #include <netif.h> 65ca987d46SWarner Losh #include <bootp.h> 66ca987d46SWarner Losh #include <bootparam.h> 67ca987d46SWarner Losh 68ca987d46SWarner Losh #include "dev_net.h" 69ca987d46SWarner Losh #include "bootstrap.h" 70ca987d46SWarner Losh 71ca987d46SWarner Losh #ifdef NETIF_DEBUG 72ca987d46SWarner Losh int debug = 0; 73ca987d46SWarner Losh #endif 74ca987d46SWarner Losh 75ca987d46SWarner Losh static char *netdev_name; 76ca987d46SWarner Losh static int netdev_sock = -1; 77ca987d46SWarner Losh static int netdev_opens; 78ca987d46SWarner Losh 79ca987d46SWarner Losh static int net_init(void); 80ca987d46SWarner Losh static int net_open(struct open_file *, ...); 81ca987d46SWarner Losh static int net_close(struct open_file *); 82ca987d46SWarner Losh static void net_cleanup(void); 83ca987d46SWarner Losh static int net_strategy(void *, int, daddr_t, size_t, char *, size_t *); 84ca987d46SWarner Losh static int net_print(int); 85ca987d46SWarner Losh 86ca987d46SWarner Losh static int net_getparams(int sock); 87ca987d46SWarner Losh 88ca987d46SWarner Losh struct devsw netdev = { 89ca987d46SWarner Losh "net", 90ca987d46SWarner Losh DEVT_NET, 91ca987d46SWarner Losh net_init, 92ca987d46SWarner Losh net_strategy, 93ca987d46SWarner Losh net_open, 94ca987d46SWarner Losh net_close, 95ca987d46SWarner Losh noioctl, 96ca987d46SWarner Losh net_print, 97ca987d46SWarner Losh net_cleanup 98ca987d46SWarner Losh }; 99ca987d46SWarner Losh 100ca987d46SWarner Losh static struct uri_scheme { 101ca987d46SWarner Losh const char *scheme; 102ca987d46SWarner Losh int proto; 103ca987d46SWarner Losh } uri_schemes[] = { 104ca987d46SWarner Losh { "tftp:/", NET_TFTP }, 105ca987d46SWarner Losh { "nfs:/", NET_NFS }, 106ca987d46SWarner Losh }; 107ca987d46SWarner Losh 108ca987d46SWarner Losh static int 109ca987d46SWarner Losh net_init(void) 110ca987d46SWarner Losh { 111ca987d46SWarner Losh 112ca987d46SWarner Losh return (0); 113ca987d46SWarner Losh } 114ca987d46SWarner Losh 115ca987d46SWarner Losh /* 116ca987d46SWarner Losh * Called by devopen after it sets f->f_dev to our devsw entry. 117ca987d46SWarner Losh * This opens the low-level device and sets f->f_devdata. 118ca987d46SWarner Losh * This is declared with variable arguments... 119ca987d46SWarner Losh */ 120ca987d46SWarner Losh static int 121ca987d46SWarner Losh net_open(struct open_file *f, ...) 122ca987d46SWarner Losh { 123ca987d46SWarner Losh struct iodesc *d; 124ca987d46SWarner Losh va_list args; 125e49f2c66SKyle Evans struct devdesc *dev; 126e49f2c66SKyle Evans const char *devname; /* Device part of file name (or NULL). */ 127ca987d46SWarner Losh int error = 0; 128ca987d46SWarner Losh 129ca987d46SWarner Losh va_start(args, f); 130e49f2c66SKyle Evans dev = va_arg(args, struct devdesc *); 131ca987d46SWarner Losh va_end(args); 132ca987d46SWarner Losh 133e49f2c66SKyle Evans devname = dev->d_dev->dv_name; 134ca987d46SWarner Losh /* Before opening another interface, close the previous one first. */ 135ca987d46SWarner Losh if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0) 136ca987d46SWarner Losh net_cleanup(); 137ca987d46SWarner Losh 138ca987d46SWarner Losh /* On first open, do netif open, mount, etc. */ 139ca987d46SWarner Losh if (netdev_opens == 0) { 140ca987d46SWarner Losh /* Find network interface. */ 141ca987d46SWarner Losh if (netdev_sock < 0) { 142e49f2c66SKyle Evans netdev_sock = netif_open(dev); 143ca987d46SWarner Losh if (netdev_sock < 0) { 1441a25c51eSToomas Soome printf("%s: netif_open() failed\n", __func__); 145ca987d46SWarner Losh return (ENXIO); 146ca987d46SWarner Losh } 147ca987d46SWarner Losh netdev_name = strdup(devname); 148ca987d46SWarner Losh #ifdef NETIF_DEBUG 149ca987d46SWarner Losh if (debug) 1501a25c51eSToomas Soome printf("%s: netif_open() succeeded\n", 1511a25c51eSToomas Soome __func__); 152ca987d46SWarner Losh #endif 153ca987d46SWarner Losh } 154ca987d46SWarner Losh /* 155ca987d46SWarner Losh * If network params were not set by netif_open(), try to get 156ca987d46SWarner Losh * them via bootp, rarp, etc. 157ca987d46SWarner Losh */ 158ca987d46SWarner Losh if (rootip.s_addr == 0) { 159ca987d46SWarner Losh /* Get root IP address, and path, etc. */ 160ca987d46SWarner Losh error = net_getparams(netdev_sock); 161ca987d46SWarner Losh if (error) { 162ca987d46SWarner Losh /* getparams makes its own noise */ 163ca987d46SWarner Losh free(netdev_name); 164ca987d46SWarner Losh netif_close(netdev_sock); 165ca987d46SWarner Losh netdev_sock = -1; 166ca987d46SWarner Losh return (error); 167ca987d46SWarner Losh } 168ca987d46SWarner Losh } 169ca987d46SWarner Losh /* 170ca987d46SWarner Losh * Set the variables required by the kernel's nfs_diskless 171ca987d46SWarner Losh * mechanism. This is the minimum set of variables required to 172ca987d46SWarner Losh * mount a root filesystem without needing to obtain additional 173ca987d46SWarner Losh * info from bootp or other sources. 174ca987d46SWarner Losh */ 175ca987d46SWarner Losh d = socktodesc(netdev_sock); 176ca987d46SWarner Losh setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 1); 177ca987d46SWarner Losh setenv("boot.netif.ip", inet_ntoa(myip), 1); 178ca987d46SWarner Losh setenv("boot.netif.netmask", intoa(netmask), 1); 179ca987d46SWarner Losh setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 180ca987d46SWarner Losh setenv("boot.netif.server", inet_ntoa(rootip), 1); 181ca987d46SWarner Losh if (netproto == NET_TFTP) { 182ca987d46SWarner Losh setenv("boot.tftproot.server", inet_ntoa(rootip), 1); 183ca987d46SWarner Losh setenv("boot.tftproot.path", rootpath, 1); 184ca987d46SWarner Losh } else if (netproto == NET_NFS) { 185ca987d46SWarner Losh setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 186ca987d46SWarner Losh setenv("boot.nfsroot.path", rootpath, 1); 187ca987d46SWarner Losh } 188ca987d46SWarner Losh if (intf_mtu != 0) { 189ca987d46SWarner Losh char mtu[16]; 190ca987d46SWarner Losh snprintf(mtu, sizeof(mtu), "%u", intf_mtu); 191ca987d46SWarner Losh setenv("boot.netif.mtu", mtu, 1); 192ca987d46SWarner Losh } 193ca987d46SWarner Losh 194ca987d46SWarner Losh } 195ca987d46SWarner Losh netdev_opens++; 19609001b5cSWarner Losh f->f_devdata = &netdev_sock; 197ca987d46SWarner Losh return (error); 198ca987d46SWarner Losh } 199ca987d46SWarner Losh 200ca987d46SWarner Losh static int 201ca987d46SWarner Losh net_close(struct open_file *f) 202ca987d46SWarner Losh { 203ca987d46SWarner Losh 204ca987d46SWarner Losh #ifdef NETIF_DEBUG 205ca987d46SWarner Losh if (debug) 2061a25c51eSToomas Soome printf("%s: opens=%d\n", __func__, netdev_opens); 207ca987d46SWarner Losh #endif 20809001b5cSWarner Losh 20909001b5cSWarner Losh f->f_devdata = NULL; 21009001b5cSWarner Losh 211ca987d46SWarner Losh return (0); 212ca987d46SWarner Losh } 213ca987d46SWarner Losh 214ca987d46SWarner Losh static void 215ca987d46SWarner Losh net_cleanup(void) 216ca987d46SWarner Losh { 217ca987d46SWarner Losh 218ca987d46SWarner Losh if (netdev_sock >= 0) { 219ca987d46SWarner Losh #ifdef NETIF_DEBUG 220ca987d46SWarner Losh if (debug) 2211a25c51eSToomas Soome printf("%s: calling netif_close()\n", __func__); 222ca987d46SWarner Losh #endif 223ca987d46SWarner Losh rootip.s_addr = 0; 224ca987d46SWarner Losh free(netdev_name); 225ca987d46SWarner Losh netif_close(netdev_sock); 226ca987d46SWarner Losh netdev_sock = -1; 227ca987d46SWarner Losh } 228ca987d46SWarner Losh } 229ca987d46SWarner Losh 230ca987d46SWarner Losh static int 231ca987d46SWarner Losh net_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, 232ca987d46SWarner Losh size_t *rsize) 233ca987d46SWarner Losh { 234ca987d46SWarner Losh 235ca987d46SWarner Losh return (EIO); 236ca987d46SWarner Losh } 237ca987d46SWarner Losh 238ca987d46SWarner Losh #define SUPPORT_BOOTP 239ca987d46SWarner Losh 240ca987d46SWarner Losh /* 241ca987d46SWarner Losh * Get info for NFS boot: our IP address, our hostname, 242ca987d46SWarner Losh * server IP address, and our root path on the server. 243ca987d46SWarner Losh * There are two ways to do this: The old, Sun way, 244ca987d46SWarner Losh * and the more modern, BOOTP way. (RFC951, RFC1048) 245ca987d46SWarner Losh * 246ca987d46SWarner Losh * The default is to use the Sun bootparams RPC 247ca987d46SWarner Losh * (because that is what the kernel will do). 248ca987d46SWarner Losh * MD code can make try_bootp initialied data, 249ca987d46SWarner Losh * which will override this common definition. 250ca987d46SWarner Losh */ 251ca987d46SWarner Losh #ifdef SUPPORT_BOOTP 252ca987d46SWarner Losh int try_bootp = 1; 253ca987d46SWarner Losh #endif 254ca987d46SWarner Losh 255ca987d46SWarner Losh extern n_long ip_convertaddr(char *p); 256ca987d46SWarner Losh 257ca987d46SWarner Losh static int 258ca987d46SWarner Losh net_getparams(int sock) 259ca987d46SWarner Losh { 260ca987d46SWarner Losh char buf[MAXHOSTNAMELEN]; 261ca987d46SWarner Losh n_long rootaddr, smask; 262ca987d46SWarner Losh 263ca987d46SWarner Losh #ifdef SUPPORT_BOOTP 264ca987d46SWarner Losh /* 265ca987d46SWarner Losh * Try to get boot info using BOOTP. If we succeed, then 266ca987d46SWarner Losh * the server IP address, gateway, and root path will all 267ca987d46SWarner Losh * be initialized. If any remain uninitialized, we will 268ca987d46SWarner Losh * use RARP and RPC/bootparam (the Sun way) to get them. 269ca987d46SWarner Losh */ 270ca987d46SWarner Losh if (try_bootp) 271ca987d46SWarner Losh bootp(sock); 272ca987d46SWarner Losh if (myip.s_addr != 0) 273ca987d46SWarner Losh goto exit; 274ca987d46SWarner Losh #ifdef NETIF_DEBUG 275ca987d46SWarner Losh if (debug) 2761a25c51eSToomas Soome printf("%s: BOOTP failed, trying RARP/RPC...\n", __func__); 277ca987d46SWarner Losh #endif 278ca987d46SWarner Losh #endif 279ca987d46SWarner Losh 280ca987d46SWarner Losh /* 281ca987d46SWarner Losh * Use RARP to get our IP address. This also sets our 282ca987d46SWarner Losh * netmask to the "natural" default for our address. 283ca987d46SWarner Losh */ 284ca987d46SWarner Losh if (rarp_getipaddress(sock)) { 2851a25c51eSToomas Soome printf("%s: RARP failed\n", __func__); 286ca987d46SWarner Losh return (EIO); 287ca987d46SWarner Losh } 2881a25c51eSToomas Soome printf("%s: client addr: %s\n", __func__, inet_ntoa(myip)); 289ca987d46SWarner Losh 290ca987d46SWarner Losh /* Get our hostname, server IP address, gateway. */ 291ca987d46SWarner Losh if (bp_whoami(sock)) { 2921a25c51eSToomas Soome printf("%s: bootparam/whoami RPC failed\n", __func__); 293ca987d46SWarner Losh return (EIO); 294ca987d46SWarner Losh } 295ca987d46SWarner Losh #ifdef NETIF_DEBUG 296ca987d46SWarner Losh if (debug) 2971a25c51eSToomas Soome printf("%s: client name: %s\n", __func__, hostname); 298ca987d46SWarner Losh #endif 299ca987d46SWarner Losh 300ca987d46SWarner Losh /* 301ca987d46SWarner Losh * Ignore the gateway from whoami (unreliable). 302ca987d46SWarner Losh * Use the "gateway" parameter instead. 303ca987d46SWarner Losh */ 304ca987d46SWarner Losh smask = 0; 305ca987d46SWarner Losh gateip.s_addr = 0; 306ca987d46SWarner Losh if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { 307ca987d46SWarner Losh /* Got it! Parse the netmask. */ 308ca987d46SWarner Losh smask = ip_convertaddr(buf); 309ca987d46SWarner Losh } 310ca987d46SWarner Losh if (smask) { 311ca987d46SWarner Losh netmask = smask; 312ca987d46SWarner Losh #ifdef NETIF_DEBUG 313ca987d46SWarner Losh if (debug) 3141a25c51eSToomas Soome printf("%s: subnet mask: %s\n", __func__, 3151a25c51eSToomas Soome intoa(netmask)); 316ca987d46SWarner Losh #endif 317ca987d46SWarner Losh } 318ca987d46SWarner Losh #ifdef NETIF_DEBUG 319ca987d46SWarner Losh if (gateip.s_addr && debug) 3201a25c51eSToomas Soome printf("%s: net gateway: %s\n", __func__, inet_ntoa(gateip)); 321ca987d46SWarner Losh #endif 322ca987d46SWarner Losh 323ca987d46SWarner Losh /* Get the root server and pathname. */ 324ca987d46SWarner Losh if (bp_getfile(sock, "root", &rootip, rootpath)) { 3251a25c51eSToomas Soome printf("%s: bootparam/getfile RPC failed\n", __func__); 326ca987d46SWarner Losh return (EIO); 327ca987d46SWarner Losh } 328ca987d46SWarner Losh exit: 329ca987d46SWarner Losh if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) 330ca987d46SWarner Losh rootip.s_addr = rootaddr; 331ca987d46SWarner Losh 332ca987d46SWarner Losh #ifdef NETIF_DEBUG 333ca987d46SWarner Losh if (debug) { 3341a25c51eSToomas Soome printf("%s: server addr: %s\n", __func__, inet_ntoa(rootip)); 3351a25c51eSToomas Soome printf("%s: server path: %s\n", __func__, rootpath); 336ca987d46SWarner Losh } 337ca987d46SWarner Losh #endif 338ca987d46SWarner Losh 339ca987d46SWarner Losh return (0); 340ca987d46SWarner Losh } 341ca987d46SWarner Losh 342ca987d46SWarner Losh static int 343ca987d46SWarner Losh net_print(int verbose) 344ca987d46SWarner Losh { 345ca987d46SWarner Losh struct netif_driver *drv; 346ca987d46SWarner Losh int i, d, cnt; 347ca987d46SWarner Losh int ret = 0; 348ca987d46SWarner Losh 349ca987d46SWarner Losh if (netif_drivers[0] == NULL) 350ca987d46SWarner Losh return (ret); 351ca987d46SWarner Losh 352ca987d46SWarner Losh printf("%s devices:", netdev.dv_name); 353ca987d46SWarner Losh if ((ret = pager_output("\n")) != 0) 354ca987d46SWarner Losh return (ret); 355ca987d46SWarner Losh 356ca987d46SWarner Losh cnt = 0; 357ca987d46SWarner Losh for (d = 0; netif_drivers[d]; d++) { 358ca987d46SWarner Losh drv = netif_drivers[d]; 359ca987d46SWarner Losh for (i = 0; i < drv->netif_nifs; i++) { 360ca987d46SWarner Losh printf("\t%s%d:", netdev.dv_name, cnt++); 361ca987d46SWarner Losh if (verbose) { 362ca987d46SWarner Losh printf(" (%s%d)", drv->netif_bname, 363ca987d46SWarner Losh drv->netif_ifs[i].dif_unit); 364ca987d46SWarner Losh } 365ca987d46SWarner Losh if ((ret = pager_output("\n")) != 0) 366ca987d46SWarner Losh return (ret); 367ca987d46SWarner Losh } 368ca987d46SWarner Losh } 369ca987d46SWarner Losh return (ret); 370ca987d46SWarner Losh } 371ca987d46SWarner Losh 372ca987d46SWarner Losh /* 373ca987d46SWarner Losh * Parses the rootpath if present 374ca987d46SWarner Losh * 375ca987d46SWarner Losh * The rootpath format can be in the form 376ca987d46SWarner Losh * <scheme>://ip/path 377ca987d46SWarner Losh * <scheme>:/path 378ca987d46SWarner Losh * 379ca987d46SWarner Losh * For compatibility with previous behaviour it also accepts as an NFS scheme 380ca987d46SWarner Losh * ip:/path 381ca987d46SWarner Losh * /path 382ca987d46SWarner Losh * 383ca987d46SWarner Losh * If an ip is set it returns it in network byte order. 384ca987d46SWarner Losh * The default scheme defined in the global netproto, if not set it defaults to 385ca987d46SWarner Losh * NFS. 386ca987d46SWarner Losh * It leaves just the pathname in the global rootpath. 387ca987d46SWarner Losh */ 388ca987d46SWarner Losh uint32_t 389a9abb859SToomas Soome net_parse_rootpath(void) 390ca987d46SWarner Losh { 391ca987d46SWarner Losh n_long addr = htonl(INADDR_NONE); 392ca987d46SWarner Losh size_t i; 393ca987d46SWarner Losh char ip[FNAME_SIZE]; 394ca987d46SWarner Losh char *ptr, *val; 395ca987d46SWarner Losh 396ca987d46SWarner Losh netproto = NET_NONE; 397ca987d46SWarner Losh 398ca987d46SWarner Losh for (i = 0; i < nitems(uri_schemes); i++) { 399ca987d46SWarner Losh if (strncmp(rootpath, uri_schemes[i].scheme, 400ca987d46SWarner Losh strlen(uri_schemes[i].scheme)) != 0) 401ca987d46SWarner Losh continue; 402ca987d46SWarner Losh 403ca987d46SWarner Losh netproto = uri_schemes[i].proto; 404ca987d46SWarner Losh break; 405ca987d46SWarner Losh } 406ca987d46SWarner Losh ptr = rootpath; 407ca987d46SWarner Losh /* Fallback for compatibility mode */ 408ca987d46SWarner Losh if (netproto == NET_NONE) { 409ca987d46SWarner Losh netproto = NET_NFS; 410ca987d46SWarner Losh (void)strsep(&ptr, ":"); 411ca987d46SWarner Losh if (ptr != NULL) { 412ca987d46SWarner Losh addr = inet_addr(rootpath); 413ca987d46SWarner Losh bcopy(ptr, rootpath, strlen(ptr) + 1); 414ca987d46SWarner Losh } 415ca987d46SWarner Losh } else { 416ca987d46SWarner Losh ptr += strlen(uri_schemes[i].scheme); 417ca987d46SWarner Losh if (*ptr == '/') { 418ca987d46SWarner Losh /* we are in the form <scheme>://, we do expect an ip */ 419ca987d46SWarner Losh ptr++; 420ca987d46SWarner Losh /* 421ca987d46SWarner Losh * XXX when http will be there we will need to check for 422ca987d46SWarner Losh * a port, but right now we do not need it yet 423ca987d46SWarner Losh */ 424ca987d46SWarner Losh val = strchr(ptr, '/'); 425ca987d46SWarner Losh if (val != NULL) { 426ca987d46SWarner Losh snprintf(ip, sizeof(ip), "%.*s", 427ca987d46SWarner Losh (int)((uintptr_t)val - (uintptr_t)ptr), 428ca987d46SWarner Losh ptr); 429ca987d46SWarner Losh addr = inet_addr(ip); 430ca987d46SWarner Losh bcopy(val, rootpath, strlen(val) + 1); 431ca987d46SWarner Losh } 432ca987d46SWarner Losh } else { 433ca987d46SWarner Losh ptr--; 434ca987d46SWarner Losh bcopy(ptr, rootpath, strlen(ptr) + 1); 435ca987d46SWarner Losh } 436ca987d46SWarner Losh } 437ca987d46SWarner Losh 438ca987d46SWarner Losh return (addr); 439ca987d46SWarner Losh } 440