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