1 /* $OpenBSD: dev_net.c,v 1.3 2014/07/13 15:31:20 mpi Exp $ */ 2 /* $NetBSD: dev_net.c,v 1.26 2011/07/17 20:54:52 joerg Exp $ */ 3 4 /*- 5 * Copyright (c) 1997 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Gordon W. Ross. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * This module implements a "raw device" interface suitable for 35 * use by the stand-alone I/O library NFS code. This interface 36 * does not support any "block" access, and exists only for the 37 * purpose of initializing the network interface, getting boot 38 * parameters, and performing the NFS mount. 39 * 40 * At open time, this does: 41 * 42 * find interface - netif_open() 43 * RARP for IP address - rarp_getipaddress() 44 * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) 45 * RPC/mountd - nfs_mount(sock, ip, path) 46 * 47 * the root file handle from mountd is saved in a global 48 * for use by the NFS open code (NFS/lookup). 49 */ 50 51 #include <sys/param.h> 52 #include <sys/socket.h> 53 #include <netinet/in.h> 54 55 #include <lib/libkern/libkern.h> 56 57 #include <lib/libsa/stand.h> 58 #include <lib/libsa/net.h> 59 #include <lib/libsa/netif.h> 60 #include <lib/libsa/nfs.h> 61 #include <lib/libsa/bootparam.h> 62 #include "dev_net.h" 63 #ifdef SUPPORT_BOOTP 64 #include <lib/libsa/bootp.h> 65 #endif 66 67 extern int nfs_root_node[]; /* XXX - get from nfs_mount() */ 68 69 static int netdev_sock = -1; 70 static int netdev_opens; 71 72 static int net_getparams(int); 73 74 #ifdef DEBUG 75 int debug; 76 #endif 77 78 /* 79 * Called by devopen after it sets f->f_dev to our devsw entry. 80 * This opens the low-level device and sets f->f_devdata. 81 * This is declared with variable arguments... 82 */ 83 int 84 net_open(struct open_file *f, ...) 85 { 86 va_list ap; 87 char *devname; /* Device part of file name (or NULL). */ 88 int error = 0; 89 90 va_start(ap, f); 91 devname = va_arg(ap, char *); 92 va_end(ap); 93 94 #ifdef NETIF_DEBUG 95 if (debug) 96 printf("%s\n", devname); 97 #endif 98 99 /* On first open, do netif open, mount, etc. */ 100 if (netdev_opens == 0) { 101 /* Find network interface. */ 102 if (netdev_sock < 0) { 103 netdev_sock = netif_open(devname); 104 if (netdev_sock < 0) { 105 printf("netif_open() failed\n"); 106 return ENXIO; 107 } 108 #ifdef NETIF_DEBUG 109 if (debug) 110 printf("netif_open() succeeded\n"); 111 #endif 112 } 113 if (rootip.s_addr == 0) { 114 /* Get root IP address, and path, etc. */ 115 error = net_getparams(netdev_sock); 116 if (error) { 117 /* getparams makes its own noise */ 118 goto fail; 119 } 120 /* Get the NFS file handle (mountd). */ 121 error = nfs_mount(netdev_sock, rootip, rootpath); 122 if (error) { 123 printf("NFS mount error=%d\n", errno); 124 rootip.s_addr = 0; 125 fail: 126 netif_close(netdev_sock); 127 netdev_sock = -1; 128 return error; 129 } 130 #ifdef NETIF_DEBUG 131 if (debug) 132 printf("NFS mount succeeded\n"); 133 #endif 134 } 135 } 136 netdev_opens++; 137 f->f_devdata = nfs_root_node; 138 return error; 139 } 140 141 int 142 net_close(struct open_file *f) 143 { 144 145 #ifdef NETIF_DEBUG 146 if (debug) 147 printf("net_close: opens=%d\n", netdev_opens); 148 #endif 149 150 /* On last close, do netif close, etc. */ 151 f->f_devdata = NULL; 152 /* Extra close call? */ 153 if (netdev_opens <= 0) 154 return 0; 155 netdev_opens--; 156 /* Not last close? */ 157 if (netdev_opens > 0) 158 return 0; 159 rootip.s_addr = 0; 160 if (netdev_sock >= 0) { 161 #ifdef NETIF_DEBUG 162 if (debug) 163 printf("net_close: calling netif_close()\n"); 164 #endif 165 netif_close(netdev_sock); 166 netdev_sock = -1; 167 } 168 return 0; 169 } 170 171 int 172 net_ioctl(struct open_file *f, u_long cmd, void *data) 173 { 174 175 return EIO; 176 } 177 178 int 179 net_strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf, 180 size_t *rsize) 181 { 182 183 return EIO; 184 } 185 186 187 /* 188 * Get info for NFS boot: our IP address, our hostname, 189 * server IP address, and our root path on the server. 190 * There are two ways to do this: The old, Sun way, 191 * and the more modern, BOOTP way. (RFC951, RFC1048) 192 * 193 * The default is to use the Sun bootparams RPC 194 * (because that is what the kernel will do). 195 * MD code can make try_bootp initialied data, 196 * which will override this common definition. 197 */ 198 #ifdef SUPPORT_BOOTP 199 int try_bootp; 200 #endif 201 202 static int 203 net_getparams(int sock) 204 { 205 char buf[MAXHOSTNAMELEN]; 206 u_int32_t smask; 207 208 #ifdef SUPPORT_BOOTP 209 /* 210 * Try to get boot info using BOOTP. If we succeed, then 211 * the server IP address, gateway, and root path will all 212 * be initialized. If any remain uninitialized, we will 213 * use RARP and RPC/bootparam (the Sun way) to get them. 214 */ 215 if (try_bootp) 216 bootp(sock); 217 if (myip.s_addr != 0) 218 return 0; 219 #ifdef NETIF_DEBUG 220 if (debug) 221 printf("BOOTP failed, trying RARP/RPC...\n"); 222 #endif 223 #endif 224 225 /* 226 * Use RARP to get our IP address. This also sets our 227 * netmask to the "natural" default for our address. 228 */ 229 if (rarp_getipaddress(sock)) { 230 printf("RARP failed\n"); 231 return EIO; 232 } 233 #ifdef NETIF_DEBUG 234 if (debug) 235 printf("client addr: %s\n", inet_ntoa(myip)); 236 #endif 237 238 /* Get our hostname, server IP address, gateway. */ 239 if (bp_whoami(sock)) { 240 printf("bootparam/whoami RPC failed\n"); 241 return EIO; 242 } 243 #ifdef NETIF_DEBUG 244 if (debug) 245 printf("client name: %s\n", hostname); 246 #endif 247 248 /* 249 * Ignore the gateway from whoami (unreliable). 250 * Use the "gateway" parameter instead. 251 */ 252 smask = 0; 253 gateip.s_addr = 0; 254 if (bp_getfile(sock, "gateway", &gateip, buf)) { 255 printf("nfs_open: gateway bootparam missing\n"); 256 } else { 257 /* Got it! Parse the netmask. */ 258 smask = inet_addr(buf); 259 } 260 if (smask) { 261 netmask = smask; 262 #ifdef NETIF_DEBUG 263 if (debug) 264 printf("subnet mask: %s\n", intoa(netmask)); 265 #endif 266 } 267 #ifdef NETIF_DEBUG 268 if (debug) 269 if (gateip.s_addr) 270 printf("net gateway: %s\n", inet_ntoa(gateip)); 271 #endif 272 273 /* Get the root server and pathname. */ 274 if (bp_getfile(sock, "root", &rootip, rootpath)) { 275 printf("bootparam/getfile RPC failed\n"); 276 return EIO; 277 } 278 279 #ifdef NETIF_DEBUG 280 if (debug) { 281 printf("server addr: %s\n", inet_ntoa(rootip)); 282 printf("server path: %s\n", rootpath); 283 } 284 #endif 285 286 return 0; 287 } 288