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 /*- 33ca987d46SWarner Losh * This module implements a "raw device" interface suitable for 34ca987d46SWarner Losh * use by the stand-alone I/O library NFS code. This interface 35ca987d46SWarner Losh * does not support any "block" access, and exists only for the 36ca987d46SWarner Losh * purpose of initializing the network interface, getting boot 37ca987d46SWarner Losh * parameters, and performing the NFS mount. 38ca987d46SWarner Losh * 39ca987d46SWarner Losh * At open time, this does: 40ca987d46SWarner Losh * 41ca987d46SWarner Losh * find interface - netif_open() 42ca987d46SWarner Losh * RARP for IP address - rarp_getipaddress() 43ca987d46SWarner Losh * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) 44ca987d46SWarner Losh * RPC/mountd - nfs_mount(sock, ip, path) 45ca987d46SWarner Losh * 46ca987d46SWarner Losh * the root file handle from mountd is saved in a global 47ca987d46SWarner Losh * for use by the NFS open code (NFS/lookup). 48ca987d46SWarner Losh */ 49ca987d46SWarner Losh 50ca987d46SWarner Losh #include <machine/stdarg.h> 51ca987d46SWarner Losh #include <sys/param.h> 52ca987d46SWarner Losh #include <sys/socket.h> 53ca987d46SWarner Losh #include <net/if.h> 54ca987d46SWarner Losh #include <netinet/in.h> 55ca987d46SWarner Losh #include <netinet/in_systm.h> 56ca987d46SWarner Losh 57ca987d46SWarner Losh #include <stand.h> 58ca987d46SWarner Losh #include <stddef.h> 59ca987d46SWarner Losh #include <string.h> 60ca987d46SWarner Losh #include <net.h> 61ca987d46SWarner Losh #include <netif.h> 62ca987d46SWarner Losh #include <bootp.h> 63ca987d46SWarner Losh #include <bootparam.h> 64ca987d46SWarner Losh 65ca987d46SWarner Losh #include "dev_net.h" 66ca987d46SWarner Losh #include "bootstrap.h" 67ca987d46SWarner Losh 68ca987d46SWarner Losh #ifdef NETIF_DEBUG 69ca987d46SWarner Losh int debug = 0; 70ca987d46SWarner Losh #endif 71ca987d46SWarner Losh 72ca987d46SWarner Losh static char *netdev_name; 73ca987d46SWarner Losh static int netdev_sock = -1; 74ca987d46SWarner Losh static int netdev_opens; 75ca987d46SWarner Losh 76ca987d46SWarner Losh static int net_init(void); 77ca987d46SWarner Losh static int net_open(struct open_file *, ...); 78ca987d46SWarner Losh static int net_close(struct open_file *); 79ca987d46SWarner Losh static void net_cleanup(void); 80ca987d46SWarner Losh static int net_strategy(void *, int, daddr_t, size_t, char *, size_t *); 81ca987d46SWarner Losh static int net_print(int); 82ca987d46SWarner Losh 83ca987d46SWarner Losh static int net_getparams(int sock); 84ca987d46SWarner Losh 85ca987d46SWarner Losh struct devsw netdev = { 86*c4f4a6c9SWarner Losh .dv_name = "net", 87*c4f4a6c9SWarner Losh .dv_type = DEVT_NET, 88*c4f4a6c9SWarner Losh .dv_init = net_init, 89*c4f4a6c9SWarner Losh .dv_strategy = net_strategy, 90*c4f4a6c9SWarner Losh .dv_open = net_open, 91*c4f4a6c9SWarner Losh .dv_close = net_close, 92*c4f4a6c9SWarner Losh .dv_ioctl = noioctl, 93*c4f4a6c9SWarner Losh .dv_print = net_print, 94*c4f4a6c9SWarner Losh .dv_cleanup = net_cleanup, 95ca987d46SWarner Losh }; 96ca987d46SWarner Losh 97ca987d46SWarner Losh static struct uri_scheme { 98ca987d46SWarner Losh const char *scheme; 99ca987d46SWarner Losh int proto; 100ca987d46SWarner Losh } uri_schemes[] = { 101ca987d46SWarner Losh { "tftp:/", NET_TFTP }, 102ca987d46SWarner Losh { "nfs:/", NET_NFS }, 103ca987d46SWarner Losh }; 104ca987d46SWarner Losh 105ca987d46SWarner Losh static int 106ca987d46SWarner Losh net_init(void) 107ca987d46SWarner Losh { 108ca987d46SWarner Losh 109ca987d46SWarner Losh return (0); 110ca987d46SWarner Losh } 111ca987d46SWarner Losh 112ca987d46SWarner Losh /* 113ca987d46SWarner Losh * Called by devopen after it sets f->f_dev to our devsw entry. 11498e805b4SToomas Soome * This opens the low-level device and sets dev->d_opendata. 115ca987d46SWarner Losh * This is declared with variable arguments... 116ca987d46SWarner Losh */ 117ca987d46SWarner Losh static int 118ca987d46SWarner Losh net_open(struct open_file *f, ...) 119ca987d46SWarner Losh { 120ca987d46SWarner Losh struct iodesc *d; 121ca987d46SWarner Losh va_list args; 122e49f2c66SKyle Evans struct devdesc *dev; 123e49f2c66SKyle Evans const char *devname; /* Device part of file name (or NULL). */ 124ca987d46SWarner Losh int error = 0; 125ca987d46SWarner Losh 126ca987d46SWarner Losh va_start(args, f); 127e49f2c66SKyle Evans dev = va_arg(args, struct devdesc *); 128ca987d46SWarner Losh va_end(args); 129ca987d46SWarner Losh 130e49f2c66SKyle Evans devname = dev->d_dev->dv_name; 131ca987d46SWarner Losh /* Before opening another interface, close the previous one first. */ 132ca987d46SWarner Losh if (netdev_sock >= 0 && strcmp(devname, netdev_name) != 0) 133ca987d46SWarner Losh net_cleanup(); 134ca987d46SWarner Losh 135ca987d46SWarner Losh /* On first open, do netif open, mount, etc. */ 136ca987d46SWarner Losh if (netdev_opens == 0) { 137ca987d46SWarner Losh /* Find network interface. */ 138ca987d46SWarner Losh if (netdev_sock < 0) { 139e49f2c66SKyle Evans netdev_sock = netif_open(dev); 140ca987d46SWarner Losh if (netdev_sock < 0) { 1411a25c51eSToomas Soome printf("%s: netif_open() failed\n", __func__); 142ca987d46SWarner Losh return (ENXIO); 143ca987d46SWarner Losh } 144ca987d46SWarner Losh netdev_name = strdup(devname); 145ca987d46SWarner Losh #ifdef NETIF_DEBUG 146ca987d46SWarner Losh if (debug) 1471a25c51eSToomas Soome printf("%s: netif_open() succeeded\n", 1481a25c51eSToomas Soome __func__); 149ca987d46SWarner Losh #endif 150ca987d46SWarner Losh } 151ca987d46SWarner Losh /* 152ca987d46SWarner Losh * If network params were not set by netif_open(), try to get 153ca987d46SWarner Losh * them via bootp, rarp, etc. 154ca987d46SWarner Losh */ 155ca987d46SWarner Losh if (rootip.s_addr == 0) { 156ca987d46SWarner Losh /* Get root IP address, and path, etc. */ 157ca987d46SWarner Losh error = net_getparams(netdev_sock); 158ca987d46SWarner Losh if (error) { 159ca987d46SWarner Losh /* getparams makes its own noise */ 160ca987d46SWarner Losh free(netdev_name); 161ca987d46SWarner Losh netif_close(netdev_sock); 162ca987d46SWarner Losh netdev_sock = -1; 163ca987d46SWarner Losh return (error); 164ca987d46SWarner Losh } 165ca987d46SWarner Losh } 166ca987d46SWarner Losh /* 167ca987d46SWarner Losh * Set the variables required by the kernel's nfs_diskless 168ca987d46SWarner Losh * mechanism. This is the minimum set of variables required to 169ca987d46SWarner Losh * mount a root filesystem without needing to obtain additional 170ca987d46SWarner Losh * info from bootp or other sources. 171ca987d46SWarner Losh */ 172ca987d46SWarner Losh d = socktodesc(netdev_sock); 173ca987d46SWarner Losh setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 1); 174ca987d46SWarner Losh setenv("boot.netif.ip", inet_ntoa(myip), 1); 175ca987d46SWarner Losh setenv("boot.netif.netmask", intoa(netmask), 1); 176ca987d46SWarner Losh setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 177ca987d46SWarner Losh setenv("boot.netif.server", inet_ntoa(rootip), 1); 178ca987d46SWarner Losh if (netproto == NET_TFTP) { 179ca987d46SWarner Losh setenv("boot.tftproot.server", inet_ntoa(rootip), 1); 180ca987d46SWarner Losh setenv("boot.tftproot.path", rootpath, 1); 181ca987d46SWarner Losh } else if (netproto == NET_NFS) { 182ca987d46SWarner Losh setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 183ca987d46SWarner Losh setenv("boot.nfsroot.path", rootpath, 1); 184ca987d46SWarner Losh } 185ca987d46SWarner Losh if (intf_mtu != 0) { 186ca987d46SWarner Losh char mtu[16]; 187ca987d46SWarner Losh snprintf(mtu, sizeof(mtu), "%u", intf_mtu); 188ca987d46SWarner Losh setenv("boot.netif.mtu", mtu, 1); 189ca987d46SWarner Losh } 190ca987d46SWarner Losh 191ca987d46SWarner Losh } 192ca987d46SWarner Losh netdev_opens++; 19398e805b4SToomas Soome dev->d_opendata = &netdev_sock; 194ca987d46SWarner Losh return (error); 195ca987d46SWarner Losh } 196ca987d46SWarner Losh 197ca987d46SWarner Losh static int 198ca987d46SWarner Losh net_close(struct open_file *f) 199ca987d46SWarner Losh { 20098e805b4SToomas Soome struct devdesc *dev; 201ca987d46SWarner Losh 202ca987d46SWarner Losh #ifdef NETIF_DEBUG 203ca987d46SWarner Losh if (debug) 2041a25c51eSToomas Soome printf("%s: opens=%d\n", __func__, netdev_opens); 205ca987d46SWarner Losh #endif 20609001b5cSWarner Losh 20798e805b4SToomas Soome dev = f->f_devdata; 20898e805b4SToomas Soome dev->d_opendata = NULL; 20909001b5cSWarner Losh 210ca987d46SWarner Losh return (0); 211ca987d46SWarner Losh } 212ca987d46SWarner Losh 213ca987d46SWarner Losh static void 214ca987d46SWarner Losh net_cleanup(void) 215ca987d46SWarner Losh { 216ca987d46SWarner Losh 217ca987d46SWarner Losh if (netdev_sock >= 0) { 218ca987d46SWarner Losh #ifdef NETIF_DEBUG 219ca987d46SWarner Losh if (debug) 2201a25c51eSToomas Soome printf("%s: calling netif_close()\n", __func__); 221ca987d46SWarner Losh #endif 222ca987d46SWarner Losh rootip.s_addr = 0; 223ca987d46SWarner Losh free(netdev_name); 224ca987d46SWarner Losh netif_close(netdev_sock); 225ca987d46SWarner Losh netdev_sock = -1; 226ca987d46SWarner Losh } 227ca987d46SWarner Losh } 228ca987d46SWarner Losh 229ca987d46SWarner Losh static int 230ca987d46SWarner Losh net_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, 231ca987d46SWarner Losh size_t *rsize) 232ca987d46SWarner Losh { 233ca987d46SWarner Losh 234ca987d46SWarner Losh return (EIO); 235ca987d46SWarner Losh } 236ca987d46SWarner Losh 237ca987d46SWarner Losh #define SUPPORT_BOOTP 238ca987d46SWarner Losh 239ca987d46SWarner Losh /* 240ca987d46SWarner Losh * Get info for NFS boot: our IP address, our hostname, 241ca987d46SWarner Losh * server IP address, and our root path on the server. 242ca987d46SWarner Losh * There are two ways to do this: The old, Sun way, 243ca987d46SWarner Losh * and the more modern, BOOTP way. (RFC951, RFC1048) 244ca987d46SWarner Losh * 245ca987d46SWarner Losh * The default is to use the Sun bootparams RPC 246ca987d46SWarner Losh * (because that is what the kernel will do). 247ca987d46SWarner Losh * MD code can make try_bootp initialied data, 248ca987d46SWarner Losh * which will override this common definition. 249ca987d46SWarner Losh */ 250ca987d46SWarner Losh #ifdef SUPPORT_BOOTP 251ca987d46SWarner Losh int try_bootp = 1; 252ca987d46SWarner Losh #endif 253ca987d46SWarner Losh 254ca987d46SWarner Losh extern n_long ip_convertaddr(char *p); 255ca987d46SWarner Losh 256ca987d46SWarner Losh static int 257ca987d46SWarner Losh net_getparams(int sock) 258ca987d46SWarner Losh { 259ca987d46SWarner Losh char buf[MAXHOSTNAMELEN]; 260ca987d46SWarner Losh n_long rootaddr, smask; 261ca987d46SWarner Losh 262ca987d46SWarner Losh #ifdef SUPPORT_BOOTP 263ca987d46SWarner Losh /* 264ca987d46SWarner Losh * Try to get boot info using BOOTP. If we succeed, then 265ca987d46SWarner Losh * the server IP address, gateway, and root path will all 266ca987d46SWarner Losh * be initialized. If any remain uninitialized, we will 267ca987d46SWarner Losh * use RARP and RPC/bootparam (the Sun way) to get them. 268ca987d46SWarner Losh */ 269ca987d46SWarner Losh if (try_bootp) 270ca987d46SWarner Losh bootp(sock); 271ca987d46SWarner Losh if (myip.s_addr != 0) 272ca987d46SWarner Losh goto exit; 273ca987d46SWarner Losh #ifdef NETIF_DEBUG 274ca987d46SWarner Losh if (debug) 2751a25c51eSToomas Soome printf("%s: BOOTP failed, trying RARP/RPC...\n", __func__); 276ca987d46SWarner Losh #endif 277ca987d46SWarner Losh #endif 278ca987d46SWarner Losh 279ca987d46SWarner Losh /* 280ca987d46SWarner Losh * Use RARP to get our IP address. This also sets our 281ca987d46SWarner Losh * netmask to the "natural" default for our address. 282ca987d46SWarner Losh */ 283ca987d46SWarner Losh if (rarp_getipaddress(sock)) { 2841a25c51eSToomas Soome printf("%s: RARP failed\n", __func__); 285ca987d46SWarner Losh return (EIO); 286ca987d46SWarner Losh } 2871a25c51eSToomas Soome printf("%s: client addr: %s\n", __func__, inet_ntoa(myip)); 288ca987d46SWarner Losh 289ca987d46SWarner Losh /* Get our hostname, server IP address, gateway. */ 290ca987d46SWarner Losh if (bp_whoami(sock)) { 2911a25c51eSToomas Soome printf("%s: bootparam/whoami RPC failed\n", __func__); 292ca987d46SWarner Losh return (EIO); 293ca987d46SWarner Losh } 294ca987d46SWarner Losh #ifdef NETIF_DEBUG 295ca987d46SWarner Losh if (debug) 2961a25c51eSToomas Soome printf("%s: client name: %s\n", __func__, hostname); 297ca987d46SWarner Losh #endif 298ca987d46SWarner Losh 299ca987d46SWarner Losh /* 300ca987d46SWarner Losh * Ignore the gateway from whoami (unreliable). 301ca987d46SWarner Losh * Use the "gateway" parameter instead. 302ca987d46SWarner Losh */ 303ca987d46SWarner Losh smask = 0; 304ca987d46SWarner Losh gateip.s_addr = 0; 305ca987d46SWarner Losh if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { 306ca987d46SWarner Losh /* Got it! Parse the netmask. */ 307ca987d46SWarner Losh smask = ip_convertaddr(buf); 308ca987d46SWarner Losh } 309ca987d46SWarner Losh if (smask) { 310ca987d46SWarner Losh netmask = smask; 311ca987d46SWarner Losh #ifdef NETIF_DEBUG 312ca987d46SWarner Losh if (debug) 3131a25c51eSToomas Soome printf("%s: subnet mask: %s\n", __func__, 3141a25c51eSToomas Soome intoa(netmask)); 315ca987d46SWarner Losh #endif 316ca987d46SWarner Losh } 317ca987d46SWarner Losh #ifdef NETIF_DEBUG 318ca987d46SWarner Losh if (gateip.s_addr && debug) 3191a25c51eSToomas Soome printf("%s: net gateway: %s\n", __func__, inet_ntoa(gateip)); 320ca987d46SWarner Losh #endif 321ca987d46SWarner Losh 322ca987d46SWarner Losh /* Get the root server and pathname. */ 323ca987d46SWarner Losh if (bp_getfile(sock, "root", &rootip, rootpath)) { 3241a25c51eSToomas Soome printf("%s: bootparam/getfile RPC failed\n", __func__); 325ca987d46SWarner Losh return (EIO); 326ca987d46SWarner Losh } 327ca987d46SWarner Losh exit: 328ca987d46SWarner Losh if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) 329ca987d46SWarner Losh rootip.s_addr = rootaddr; 330ca987d46SWarner Losh 331ca987d46SWarner Losh #ifdef NETIF_DEBUG 332ca987d46SWarner Losh if (debug) { 3331a25c51eSToomas Soome printf("%s: server addr: %s\n", __func__, inet_ntoa(rootip)); 3341a25c51eSToomas Soome printf("%s: server path: %s\n", __func__, rootpath); 335ca987d46SWarner Losh } 336ca987d46SWarner Losh #endif 337ca987d46SWarner Losh 338ca987d46SWarner Losh return (0); 339ca987d46SWarner Losh } 340ca987d46SWarner Losh 341ca987d46SWarner Losh static int 342ca987d46SWarner Losh net_print(int verbose) 343ca987d46SWarner Losh { 344ca987d46SWarner Losh struct netif_driver *drv; 345ca987d46SWarner Losh int i, d, cnt; 346ca987d46SWarner Losh int ret = 0; 347ca987d46SWarner Losh 348ca987d46SWarner Losh if (netif_drivers[0] == NULL) 349ca987d46SWarner Losh return (ret); 350ca987d46SWarner Losh 351ca987d46SWarner Losh printf("%s devices:", netdev.dv_name); 352ca987d46SWarner Losh if ((ret = pager_output("\n")) != 0) 353ca987d46SWarner Losh return (ret); 354ca987d46SWarner Losh 355ca987d46SWarner Losh cnt = 0; 356ca987d46SWarner Losh for (d = 0; netif_drivers[d]; d++) { 357ca987d46SWarner Losh drv = netif_drivers[d]; 358ca987d46SWarner Losh for (i = 0; i < drv->netif_nifs; i++) { 359ca987d46SWarner Losh printf("\t%s%d:", netdev.dv_name, cnt++); 360ca987d46SWarner Losh if (verbose) { 361ca987d46SWarner Losh printf(" (%s%d)", drv->netif_bname, 362ca987d46SWarner Losh drv->netif_ifs[i].dif_unit); 363ca987d46SWarner Losh } 364ca987d46SWarner Losh if ((ret = pager_output("\n")) != 0) 365ca987d46SWarner Losh return (ret); 366ca987d46SWarner Losh } 367ca987d46SWarner Losh } 368ca987d46SWarner Losh return (ret); 369ca987d46SWarner Losh } 370ca987d46SWarner Losh 371ca987d46SWarner Losh /* 372ca987d46SWarner Losh * Parses the rootpath if present 373ca987d46SWarner Losh * 374ca987d46SWarner Losh * The rootpath format can be in the form 375ca987d46SWarner Losh * <scheme>://ip/path 376ca987d46SWarner Losh * <scheme>:/path 377ca987d46SWarner Losh * 378ca987d46SWarner Losh * For compatibility with previous behaviour it also accepts as an NFS scheme 379ca987d46SWarner Losh * ip:/path 380ca987d46SWarner Losh * /path 381ca987d46SWarner Losh * 382ca987d46SWarner Losh * If an ip is set it returns it in network byte order. 383ca987d46SWarner Losh * The default scheme defined in the global netproto, if not set it defaults to 384ca987d46SWarner Losh * NFS. 385ca987d46SWarner Losh * It leaves just the pathname in the global rootpath. 386ca987d46SWarner Losh */ 387ca987d46SWarner Losh uint32_t 388a9abb859SToomas Soome net_parse_rootpath(void) 389ca987d46SWarner Losh { 390ca987d46SWarner Losh n_long addr = htonl(INADDR_NONE); 391ca987d46SWarner Losh size_t i; 392ca987d46SWarner Losh char ip[FNAME_SIZE]; 393ca987d46SWarner Losh char *ptr, *val; 394ca987d46SWarner Losh 395ca987d46SWarner Losh netproto = NET_NONE; 396ca987d46SWarner Losh 397ca987d46SWarner Losh for (i = 0; i < nitems(uri_schemes); i++) { 398ca987d46SWarner Losh if (strncmp(rootpath, uri_schemes[i].scheme, 399ca987d46SWarner Losh strlen(uri_schemes[i].scheme)) != 0) 400ca987d46SWarner Losh continue; 401ca987d46SWarner Losh 402ca987d46SWarner Losh netproto = uri_schemes[i].proto; 403ca987d46SWarner Losh break; 404ca987d46SWarner Losh } 405ca987d46SWarner Losh ptr = rootpath; 406ca987d46SWarner Losh /* Fallback for compatibility mode */ 407ca987d46SWarner Losh if (netproto == NET_NONE) { 408ca987d46SWarner Losh netproto = NET_NFS; 409ca987d46SWarner Losh (void)strsep(&ptr, ":"); 410ca987d46SWarner Losh if (ptr != NULL) { 411ca987d46SWarner Losh addr = inet_addr(rootpath); 412ca987d46SWarner Losh bcopy(ptr, rootpath, strlen(ptr) + 1); 413ca987d46SWarner Losh } 414ca987d46SWarner Losh } else { 415ca987d46SWarner Losh ptr += strlen(uri_schemes[i].scheme); 416ca987d46SWarner Losh if (*ptr == '/') { 417ca987d46SWarner Losh /* we are in the form <scheme>://, we do expect an ip */ 418ca987d46SWarner Losh ptr++; 419ca987d46SWarner Losh /* 420ca987d46SWarner Losh * XXX when http will be there we will need to check for 421ca987d46SWarner Losh * a port, but right now we do not need it yet 422ca987d46SWarner Losh */ 423ca987d46SWarner Losh val = strchr(ptr, '/'); 424ca987d46SWarner Losh if (val != NULL) { 425ca987d46SWarner Losh snprintf(ip, sizeof(ip), "%.*s", 426ca987d46SWarner Losh (int)((uintptr_t)val - (uintptr_t)ptr), 427ca987d46SWarner Losh ptr); 428ca987d46SWarner Losh addr = inet_addr(ip); 429ca987d46SWarner Losh bcopy(val, rootpath, strlen(val) + 1); 430ca987d46SWarner Losh } 431ca987d46SWarner Losh } else { 432ca987d46SWarner Losh ptr--; 433ca987d46SWarner Losh bcopy(ptr, rootpath, strlen(ptr) + 1); 434ca987d46SWarner Losh } 435ca987d46SWarner Losh } 436ca987d46SWarner Losh 437ca987d46SWarner Losh return (addr); 438ca987d46SWarner Losh } 439