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