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; 125*e49f2c66SKyle Evans struct devdesc *dev; 126*e49f2c66SKyle Evans const char *devname; /* Device part of file name (or NULL). */ 127ca987d46SWarner Losh int error = 0; 128ca987d46SWarner Losh 129ca987d46SWarner Losh va_start(args, f); 130*e49f2c66SKyle Evans dev = va_arg(args, struct devdesc *); 131ca987d46SWarner Losh va_end(args); 132ca987d46SWarner Losh 133*e49f2c66SKyle 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) { 142*e49f2c66SKyle Evans netdev_sock = netif_open(dev); 143ca987d46SWarner Losh if (netdev_sock < 0) { 144ca987d46SWarner Losh printf("net_open: netif_open() failed\n"); 145ca987d46SWarner Losh return (ENXIO); 146ca987d46SWarner Losh } 147ca987d46SWarner Losh netdev_name = strdup(devname); 148ca987d46SWarner Losh #ifdef NETIF_DEBUG 149ca987d46SWarner Losh if (debug) 150ca987d46SWarner Losh printf("net_open: netif_open() succeeded\n"); 151ca987d46SWarner Losh #endif 152ca987d46SWarner Losh } 153ca987d46SWarner Losh /* 154ca987d46SWarner Losh * If network params were not set by netif_open(), try to get 155ca987d46SWarner Losh * them via bootp, rarp, etc. 156ca987d46SWarner Losh */ 157ca987d46SWarner Losh if (rootip.s_addr == 0) { 158ca987d46SWarner Losh /* Get root IP address, and path, etc. */ 159ca987d46SWarner Losh error = net_getparams(netdev_sock); 160ca987d46SWarner Losh if (error) { 161ca987d46SWarner Losh /* getparams makes its own noise */ 162ca987d46SWarner Losh free(netdev_name); 163ca987d46SWarner Losh netif_close(netdev_sock); 164ca987d46SWarner Losh netdev_sock = -1; 165ca987d46SWarner Losh return (error); 166ca987d46SWarner Losh } 167ca987d46SWarner Losh } 168ca987d46SWarner Losh /* 169ca987d46SWarner Losh * Set the variables required by the kernel's nfs_diskless 170ca987d46SWarner Losh * mechanism. This is the minimum set of variables required to 171ca987d46SWarner Losh * mount a root filesystem without needing to obtain additional 172ca987d46SWarner Losh * info from bootp or other sources. 173ca987d46SWarner Losh */ 174ca987d46SWarner Losh d = socktodesc(netdev_sock); 175ca987d46SWarner Losh setenv("boot.netif.hwaddr", ether_sprintf(d->myea), 1); 176ca987d46SWarner Losh setenv("boot.netif.ip", inet_ntoa(myip), 1); 177ca987d46SWarner Losh setenv("boot.netif.netmask", intoa(netmask), 1); 178ca987d46SWarner Losh setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 179ca987d46SWarner Losh setenv("boot.netif.server", inet_ntoa(rootip), 1); 180ca987d46SWarner Losh if (netproto == NET_TFTP) { 181ca987d46SWarner Losh setenv("boot.tftproot.server", inet_ntoa(rootip), 1); 182ca987d46SWarner Losh setenv("boot.tftproot.path", rootpath, 1); 183ca987d46SWarner Losh } else if (netproto == NET_NFS) { 184ca987d46SWarner Losh setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 185ca987d46SWarner Losh setenv("boot.nfsroot.path", rootpath, 1); 186ca987d46SWarner Losh } 187ca987d46SWarner Losh if (intf_mtu != 0) { 188ca987d46SWarner Losh char mtu[16]; 189ca987d46SWarner Losh snprintf(mtu, sizeof(mtu), "%u", intf_mtu); 190ca987d46SWarner Losh setenv("boot.netif.mtu", mtu, 1); 191ca987d46SWarner Losh } 192ca987d46SWarner Losh 193ca987d46SWarner Losh } 194ca987d46SWarner Losh netdev_opens++; 19509001b5cSWarner Losh f->f_devdata = &netdev_sock; 196ca987d46SWarner Losh return (error); 197ca987d46SWarner Losh } 198ca987d46SWarner Losh 199ca987d46SWarner Losh static int 200ca987d46SWarner Losh net_close(struct open_file *f) 201ca987d46SWarner Losh { 202ca987d46SWarner Losh 203ca987d46SWarner Losh #ifdef NETIF_DEBUG 204ca987d46SWarner Losh if (debug) 205ca987d46SWarner Losh printf("net_close: opens=%d\n", netdev_opens); 206ca987d46SWarner Losh #endif 20709001b5cSWarner Losh 20809001b5cSWarner Losh f->f_devdata = 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) 220ca987d46SWarner Losh printf("net_cleanup: calling netif_close()\n"); 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) 275ca987d46SWarner Losh printf("net_open: BOOTP failed, trying RARP/RPC...\n"); 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)) { 284ca987d46SWarner Losh printf("net_open: RARP failed\n"); 285ca987d46SWarner Losh return (EIO); 286ca987d46SWarner Losh } 287ca987d46SWarner Losh printf("net_open: client addr: %s\n", inet_ntoa(myip)); 288ca987d46SWarner Losh 289ca987d46SWarner Losh /* Get our hostname, server IP address, gateway. */ 290ca987d46SWarner Losh if (bp_whoami(sock)) { 291ca987d46SWarner Losh printf("net_open: bootparam/whoami RPC failed\n"); 292ca987d46SWarner Losh return (EIO); 293ca987d46SWarner Losh } 294ca987d46SWarner Losh #ifdef NETIF_DEBUG 295ca987d46SWarner Losh if (debug) 296ca987d46SWarner Losh printf("net_open: client name: %s\n", 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) 313ca987d46SWarner Losh printf("net_open: subnet mask: %s\n", intoa(netmask)); 314ca987d46SWarner Losh #endif 315ca987d46SWarner Losh } 316ca987d46SWarner Losh #ifdef NETIF_DEBUG 317ca987d46SWarner Losh if (gateip.s_addr && debug) 318ca987d46SWarner Losh printf("net_open: net gateway: %s\n", inet_ntoa(gateip)); 319ca987d46SWarner Losh #endif 320ca987d46SWarner Losh 321ca987d46SWarner Losh /* Get the root server and pathname. */ 322ca987d46SWarner Losh if (bp_getfile(sock, "root", &rootip, rootpath)) { 323ca987d46SWarner Losh printf("net_open: bootparam/getfile RPC failed\n"); 324ca987d46SWarner Losh return (EIO); 325ca987d46SWarner Losh } 326ca987d46SWarner Losh exit: 327ca987d46SWarner Losh if ((rootaddr = net_parse_rootpath()) != INADDR_NONE) 328ca987d46SWarner Losh rootip.s_addr = rootaddr; 329ca987d46SWarner Losh 330ca987d46SWarner Losh #ifdef NETIF_DEBUG 331ca987d46SWarner Losh if (debug) { 332ca987d46SWarner Losh printf("net_open: server addr: %s\n", inet_ntoa(rootip)); 333ca987d46SWarner Losh printf("net_open: server path: %s\n", rootpath); 334ca987d46SWarner Losh } 335ca987d46SWarner Losh #endif 336ca987d46SWarner Losh 337ca987d46SWarner Losh return (0); 338ca987d46SWarner Losh } 339ca987d46SWarner Losh 340ca987d46SWarner Losh static int 341ca987d46SWarner Losh net_print(int verbose) 342ca987d46SWarner Losh { 343ca987d46SWarner Losh struct netif_driver *drv; 344ca987d46SWarner Losh int i, d, cnt; 345ca987d46SWarner Losh int ret = 0; 346ca987d46SWarner Losh 347ca987d46SWarner Losh if (netif_drivers[0] == NULL) 348ca987d46SWarner Losh return (ret); 349ca987d46SWarner Losh 350ca987d46SWarner Losh printf("%s devices:", netdev.dv_name); 351ca987d46SWarner Losh if ((ret = pager_output("\n")) != 0) 352ca987d46SWarner Losh return (ret); 353ca987d46SWarner Losh 354ca987d46SWarner Losh cnt = 0; 355ca987d46SWarner Losh for (d = 0; netif_drivers[d]; d++) { 356ca987d46SWarner Losh drv = netif_drivers[d]; 357ca987d46SWarner Losh for (i = 0; i < drv->netif_nifs; i++) { 358ca987d46SWarner Losh printf("\t%s%d:", netdev.dv_name, cnt++); 359ca987d46SWarner Losh if (verbose) { 360ca987d46SWarner Losh printf(" (%s%d)", drv->netif_bname, 361ca987d46SWarner Losh drv->netif_ifs[i].dif_unit); 362ca987d46SWarner Losh } 363ca987d46SWarner Losh if ((ret = pager_output("\n")) != 0) 364ca987d46SWarner Losh return (ret); 365ca987d46SWarner Losh } 366ca987d46SWarner Losh } 367ca987d46SWarner Losh return (ret); 368ca987d46SWarner Losh } 369ca987d46SWarner Losh 370ca987d46SWarner Losh /* 371ca987d46SWarner Losh * Parses the rootpath if present 372ca987d46SWarner Losh * 373ca987d46SWarner Losh * The rootpath format can be in the form 374ca987d46SWarner Losh * <scheme>://ip/path 375ca987d46SWarner Losh * <scheme>:/path 376ca987d46SWarner Losh * 377ca987d46SWarner Losh * For compatibility with previous behaviour it also accepts as an NFS scheme 378ca987d46SWarner Losh * ip:/path 379ca987d46SWarner Losh * /path 380ca987d46SWarner Losh * 381ca987d46SWarner Losh * If an ip is set it returns it in network byte order. 382ca987d46SWarner Losh * The default scheme defined in the global netproto, if not set it defaults to 383ca987d46SWarner Losh * NFS. 384ca987d46SWarner Losh * It leaves just the pathname in the global rootpath. 385ca987d46SWarner Losh */ 386ca987d46SWarner Losh uint32_t 387a9abb859SToomas Soome net_parse_rootpath(void) 388ca987d46SWarner Losh { 389ca987d46SWarner Losh n_long addr = htonl(INADDR_NONE); 390ca987d46SWarner Losh size_t i; 391ca987d46SWarner Losh char ip[FNAME_SIZE]; 392ca987d46SWarner Losh char *ptr, *val; 393ca987d46SWarner Losh 394ca987d46SWarner Losh netproto = NET_NONE; 395ca987d46SWarner Losh 396ca987d46SWarner Losh for (i = 0; i < nitems(uri_schemes); i++) { 397ca987d46SWarner Losh if (strncmp(rootpath, uri_schemes[i].scheme, 398ca987d46SWarner Losh strlen(uri_schemes[i].scheme)) != 0) 399ca987d46SWarner Losh continue; 400ca987d46SWarner Losh 401ca987d46SWarner Losh netproto = uri_schemes[i].proto; 402ca987d46SWarner Losh break; 403ca987d46SWarner Losh } 404ca987d46SWarner Losh ptr = rootpath; 405ca987d46SWarner Losh /* Fallback for compatibility mode */ 406ca987d46SWarner Losh if (netproto == NET_NONE) { 407ca987d46SWarner Losh netproto = NET_NFS; 408ca987d46SWarner Losh (void)strsep(&ptr, ":"); 409ca987d46SWarner Losh if (ptr != NULL) { 410ca987d46SWarner Losh addr = inet_addr(rootpath); 411ca987d46SWarner Losh bcopy(ptr, rootpath, strlen(ptr) + 1); 412ca987d46SWarner Losh } 413ca987d46SWarner Losh } else { 414ca987d46SWarner Losh ptr += strlen(uri_schemes[i].scheme); 415ca987d46SWarner Losh if (*ptr == '/') { 416ca987d46SWarner Losh /* we are in the form <scheme>://, we do expect an ip */ 417ca987d46SWarner Losh ptr++; 418ca987d46SWarner Losh /* 419ca987d46SWarner Losh * XXX when http will be there we will need to check for 420ca987d46SWarner Losh * a port, but right now we do not need it yet 421ca987d46SWarner Losh */ 422ca987d46SWarner Losh val = strchr(ptr, '/'); 423ca987d46SWarner Losh if (val != NULL) { 424ca987d46SWarner Losh snprintf(ip, sizeof(ip), "%.*s", 425ca987d46SWarner Losh (int)((uintptr_t)val - (uintptr_t)ptr), 426ca987d46SWarner Losh ptr); 427ca987d46SWarner Losh addr = inet_addr(ip); 428ca987d46SWarner Losh bcopy(val, rootpath, strlen(val) + 1); 429ca987d46SWarner Losh } 430ca987d46SWarner Losh } else { 431ca987d46SWarner Losh ptr--; 432ca987d46SWarner Losh bcopy(ptr, rootpath, strlen(ptr) + 1); 433ca987d46SWarner Losh } 434ca987d46SWarner Losh } 435ca987d46SWarner Losh 436ca987d46SWarner Losh return (addr); 437ca987d46SWarner Losh } 438