dev_net.c revision 201901
1/* $NetBSD: dev_net.c,v 1.23 2008/04/28 20:24:06 martin 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#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: head/sys/boot/common/dev_net.c 201901 2010-01-09 17:09:57Z marius $"); 34 35/*- 36 * This module implements a "raw device" interface suitable for 37 * use by the stand-alone I/O library NFS code. This interface 38 * does not support any "block" access, and exists only for the 39 * purpose of initializing the network interface, getting boot 40 * parameters, and performing the NFS mount. 41 * 42 * At open time, this does: 43 * 44 * find interface - netif_open() 45 * RARP for IP address - rarp_getipaddress() 46 * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...) 47 * RPC/mountd - nfs_mount(sock, ip, path) 48 * 49 * the root file handle from mountd is saved in a global 50 * for use by the NFS open code (NFS/lookup). 51 */ 52 53#include <machine/stdarg.h> 54#include <sys/param.h> 55#include <sys/socket.h> 56#include <net/if.h> 57#include <netinet/in.h> 58#include <netinet/in_systm.h> 59 60#include <stand.h> 61#include <string.h> 62#include <net.h> 63#include <netif.h> 64#include <bootp.h> 65#include <bootparam.h> 66 67#include "dev_net.h" 68#include "bootstrap.h" 69 70#ifdef NETIF_DEBUG 71int debug = 0; 72#endif 73 74static int netdev_sock = -1; 75static int netdev_opens; 76 77static int net_init(void); 78static int net_open(struct open_file *, ...); 79static int net_close(struct open_file *); 80static int net_strategy(); 81static void net_print(int); 82 83static int net_getparams(int sock); 84 85struct devsw netdev = { 86 "net", 87 DEVT_NET, 88 net_init, 89 net_strategy, 90 net_open, 91 net_close, 92 noioctl, 93 net_print 94}; 95 96static int 97net_init(void) 98{ 99 100 return (0); 101} 102 103/* 104 * Called by devopen after it sets f->f_dev to our devsw entry. 105 * This opens the low-level device and sets f->f_devdata. 106 * This is declared with variable arguments... 107 */ 108static int 109net_open(struct open_file *f, ...) 110{ 111 va_list args; 112 char *devname; /* Device part of file name (or NULL). */ 113 int error = 0; 114 115 va_start(args, f); 116 devname = va_arg(args, char*); 117 va_end(args); 118 119 /* On first open, do netif open, mount, etc. */ 120 if (netdev_opens == 0) { 121 /* Find network interface. */ 122 if (netdev_sock < 0) { 123 netdev_sock = netif_open(devname); 124 if (netdev_sock < 0) { 125 printf("net_open: netif_open() failed\n"); 126 return (ENXIO); 127 } 128#ifdef NETIF_DEBUG 129 if (debug) 130 printf("net_open: netif_open() succeeded\n"); 131#endif 132 } 133 if (rootip.s_addr == 0) { 134 /* Get root IP address, and path, etc. */ 135 error = net_getparams(netdev_sock); 136 if (error) { 137 /* getparams makes its own noise */ 138 netif_close(netdev_sock); 139 netdev_sock = -1; 140 return (error); 141 } 142 } 143#if defined(__sparc64__) 144 netdev_opens++; 145#endif 146 } 147 netdev_opens++; 148 f->f_devdata = &netdev_sock; 149 return (error); 150} 151 152static int 153net_close(struct open_file *f) 154{ 155#ifdef NETIF_DEBUG 156 if (debug) 157 printf("net_close: opens=%d\n", netdev_opens); 158#endif 159 160 /* On last close, do netif close, etc. */ 161 f->f_devdata = NULL; 162 /* Extra close call? */ 163 if (netdev_opens <= 0) 164 return (0); 165 netdev_opens--; 166 /* Not last close? */ 167 if (netdev_opens > 0) 168 return(0); 169 rootip.s_addr = 0; 170 if (netdev_sock >= 0) { 171#ifdef NETIF_DEBUG 172 if (debug) 173 printf("net_close: calling netif_close()\n"); 174#endif 175 netif_close(netdev_sock); 176 netdev_sock = -1; 177 } 178 return (0); 179} 180 181static int 182net_strategy() 183{ 184 185 return (EIO); 186} 187 188#define SUPPORT_BOOTP 189 190/* 191 * Get info for NFS boot: our IP address, our hostname, 192 * server IP address, and our root path on the server. 193 * There are two ways to do this: The old, Sun way, 194 * and the more modern, BOOTP way. (RFC951, RFC1048) 195 * 196 * The default is to use the Sun bootparams RPC 197 * (because that is what the kernel will do). 198 * MD code can make try_bootp initialied data, 199 * which will override this common definition. 200 */ 201#ifdef SUPPORT_BOOTP 202int try_bootp = 1; 203#endif 204 205extern n_long ip_convertaddr(char *p); 206 207static int 208net_getparams(int sock) 209{ 210 char buf[MAXHOSTNAMELEN]; 211 char temp[FNAME_SIZE]; 212 struct iodesc *d; 213 int i; 214 n_long smask; 215 216#ifdef SUPPORT_BOOTP 217 /* 218 * Try to get boot info using BOOTP. If we succeed, then 219 * the server IP address, gateway, and root path will all 220 * be initialized. If any remain uninitialized, we will 221 * use RARP and RPC/bootparam (the Sun way) to get them. 222 */ 223 if (try_bootp) 224 bootp(sock, BOOTP_NONE); 225 if (myip.s_addr != 0) 226 goto exit; 227#ifdef NETIF_DEBUG 228 if (debug) 229 printf("net_open: BOOTP failed, trying RARP/RPC...\n"); 230#endif 231#endif 232 233 /* 234 * Use RARP to get our IP address. This also sets our 235 * netmask to the "natural" default for our address. 236 */ 237 if (rarp_getipaddress(sock)) { 238 printf("net_open: RARP failed\n"); 239 return (EIO); 240 } 241 printf("net_open: client addr: %s\n", inet_ntoa(myip)); 242 243 /* Get our hostname, server IP address, gateway. */ 244 if (bp_whoami(sock)) { 245 printf("net_open: bootparam/whoami RPC failed\n"); 246 return (EIO); 247 } 248#ifdef NETIF_DEBUG 249 if (debug) 250 printf("net_open: client name: %s\n", hostname); 251#endif 252 253 /* 254 * Ignore the gateway from whoami (unreliable). 255 * Use the "gateway" parameter instead. 256 */ 257 smask = 0; 258 gateip.s_addr = 0; 259 if (bp_getfile(sock, "gateway", &gateip, buf) == 0) { 260 /* Got it! Parse the netmask. */ 261 smask = ip_convertaddr(buf); 262 } 263 if (smask) { 264 netmask = smask; 265#ifdef NETIF_DEBUG 266 if (debug) 267 printf("net_open: subnet mask: %s\n", intoa(netmask)); 268#endif 269 } 270#ifdef NETIF_DEBUG 271 if (gateip.s_addr && debug) 272 printf("net_open: net gateway: %s\n", inet_ntoa(gateip)); 273#endif 274 275 /* Get the root server and pathname. */ 276 if (bp_getfile(sock, "root", &rootip, rootpath)) { 277 printf("net_open: bootparam/getfile RPC failed\n"); 278 return (EIO); 279 } 280exit: 281 /* 282 * If present, strip the server's address off of the rootpath 283 * before passing it along. This allows us to be compatible with 284 * the kernel's diskless (BOOTP_NFSROOT) booting conventions 285 */ 286 for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) 287 if (rootpath[i] == ':') 288 break; 289 if (i && i != FNAME_SIZE && rootpath[i] == ':') { 290 rootpath[i++] = '\0'; 291 if (inet_addr(&rootpath[0]) != INADDR_NONE) 292 rootip.s_addr = inet_addr(&rootpath[0]); 293 bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); 294 bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); 295 } 296#ifdef NETIF_DEBUG 297 if (debug) { 298 printf("net_open: server addr: %s\n", inet_ntoa(rootip)); 299 printf("net_open: server path: %s\n", rootpath); 300 } 301#endif 302 303 d = socktodesc(sock); 304 sprintf(temp, "%6D", d->myea, ":"); 305 setenv("boot.netif.ip", inet_ntoa(myip), 1); 306 setenv("boot.netif.netmask", intoa(netmask), 1); 307 setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 308 setenv("boot.netif.hwaddr", temp, 1); 309 setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 310 setenv("boot.nfsroot.path", rootpath, 1); 311 312 return (0); 313} 314 315static void 316net_print(int verbose) 317{ 318 struct netif_driver *drv; 319 int i, d, cnt; 320 321 cnt = 0; 322 for (d = 0; netif_drivers[d]; d++) { 323 drv = netif_drivers[d]; 324 for (i = 0; i < drv->netif_nifs; i++) { 325 printf("\t%s%d:", "net", cnt++); 326 if (verbose) 327 printf(" (%s%d)", drv->netif_bname, 328 drv->netif_ifs[i].dif_unit); 329 } 330 } 331 printf("\n"); 332} 333