1*10497fd2Schristos /* $NetBSD: dev_net.c,v 1.27 2019/03/31 20:08:45 christos Exp $ */
28e179d8eSgwr
32cf76130Sgwr /*-
42cf76130Sgwr * Copyright (c) 1997 The NetBSD Foundation, Inc.
58e179d8eSgwr * All rights reserved.
68e179d8eSgwr *
72cf76130Sgwr * This code is derived from software contributed to The NetBSD Foundation
82cf76130Sgwr * by Gordon W. Ross.
92cf76130Sgwr *
108e179d8eSgwr * Redistribution and use in source and binary forms, with or without
118e179d8eSgwr * modification, are permitted provided that the following conditions
128e179d8eSgwr * are met:
138e179d8eSgwr * 1. Redistributions of source code must retain the above copyright
148e179d8eSgwr * notice, this list of conditions and the following disclaimer.
158e179d8eSgwr * 2. Redistributions in binary form must reproduce the above copyright
168e179d8eSgwr * notice, this list of conditions and the following disclaimer in the
178e179d8eSgwr * documentation and/or other materials provided with the distribution.
188e179d8eSgwr *
192cf76130Sgwr * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
202cf76130Sgwr * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
212cf76130Sgwr * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
222cf76130Sgwr * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
232cf76130Sgwr * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
242cf76130Sgwr * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
252cf76130Sgwr * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
262cf76130Sgwr * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
272cf76130Sgwr * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
282cf76130Sgwr * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
292cf76130Sgwr * POSSIBILITY OF SUCH DAMAGE.
308e179d8eSgwr */
318e179d8eSgwr
328e179d8eSgwr /*
338e179d8eSgwr * This module implements a "raw device" interface suitable for
348e179d8eSgwr * use by the stand-alone I/O library NFS code. This interface
358e179d8eSgwr * does not support any "block" access, and exists only for the
368e179d8eSgwr * purpose of initializing the network interface, getting boot
378e179d8eSgwr * parameters, and performing the NFS mount.
388e179d8eSgwr *
398e179d8eSgwr * At open time, this does:
408e179d8eSgwr *
418e179d8eSgwr * find interface - netif_open()
428e179d8eSgwr * RARP for IP address - rarp_getipaddress()
438e179d8eSgwr * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...)
448e179d8eSgwr * RPC/mountd - nfs_mount(sock, ip, path)
458e179d8eSgwr *
468e179d8eSgwr * the root file handle from mountd is saved in a global
478e179d8eSgwr * for use by the NFS open code (NFS/lookup).
488e179d8eSgwr */
498e179d8eSgwr
508e179d8eSgwr #include <sys/param.h>
518e179d8eSgwr #include <sys/socket.h>
528e179d8eSgwr #include <net/if.h>
538e179d8eSgwr #include <netinet/in.h>
548e179d8eSgwr #include <netinet/in_systm.h>
558e179d8eSgwr
5636ff5d93Sthorpej #include <lib/libkern/libkern.h>
5736ff5d93Sthorpej
588e179d8eSgwr #include "stand.h"
598e179d8eSgwr #include "net.h"
608e179d8eSgwr #include "netif.h"
612cf76130Sgwr #include "nfs.h"
628e179d8eSgwr #include "bootparam.h"
6338c7f668Sgwr #include "dev_net.h"
6403f68714Stsutsui #ifdef SUPPORT_BOOTP
6503f68714Stsutsui #include "bootp.h"
6603f68714Stsutsui #endif
678e179d8eSgwr
688e179d8eSgwr extern int nfs_root_node[]; /* XXX - get from nfs_mount() */
698e179d8eSgwr
7023ee5602Sgwr static int netdev_sock = -1;
7138c7f668Sgwr static int netdev_opens;
728e179d8eSgwr
733f38114dStsutsui static int net_getparams(int);
742cf76130Sgwr
758e179d8eSgwr /*
768e179d8eSgwr * Called by devopen after it sets f->f_dev to our devsw entry.
778e179d8eSgwr * This opens the low-level device and sets f->f_devdata.
7838c7f668Sgwr * This is declared with variable arguments...
798e179d8eSgwr */
808e179d8eSgwr int
net_open(struct open_file * f,...)8138c7f668Sgwr net_open(struct open_file *f, ...)
828e179d8eSgwr {
8338c7f668Sgwr va_list ap;
8438c7f668Sgwr char *devname; /* Device part of file name (or NULL). */
858e179d8eSgwr int error = 0;
868e179d8eSgwr
8738c7f668Sgwr va_start(ap, f);
8838c7f668Sgwr devname = va_arg(ap, char *);
8938c7f668Sgwr va_end(ap);
9038c7f668Sgwr
9138c7f668Sgwr #ifdef NETIF_DEBUG
9238c7f668Sgwr if (debug)
93db908184Smartin printf("%s\n", devname);
9438c7f668Sgwr #endif
9538c7f668Sgwr
968e179d8eSgwr /* On first open, do netif open, mount, etc. */
9738c7f668Sgwr if (netdev_opens == 0) {
988e179d8eSgwr /* Find network interface. */
9938c7f668Sgwr if (netdev_sock < 0) {
10038c7f668Sgwr netdev_sock = netif_open(devname);
10138c7f668Sgwr if (netdev_sock < 0) {
102db908184Smartin printf("netif_open() failed\n");
1031c038e68Sisaki return ENXIO;
10438c7f668Sgwr }
105d16aceedSgmcgarry #ifdef NETIF_DEBUG
10638c7f668Sgwr if (debug)
107db908184Smartin printf("netif_open() succeeded\n");
108d16aceedSgmcgarry #endif
10938c7f668Sgwr }
11038c7f668Sgwr if (rootip.s_addr == 0) {
11138c7f668Sgwr /* Get root IP address, and path, etc. */
11238c7f668Sgwr error = net_getparams(netdev_sock);
11338c7f668Sgwr if (error) {
11438c7f668Sgwr /* getparams makes its own noise */
11538c7f668Sgwr goto fail;
11638c7f668Sgwr }
11738c7f668Sgwr /* Get the NFS file handle (mountd). */
11838c7f668Sgwr error = nfs_mount(netdev_sock, rootip, rootpath);
11938c7f668Sgwr if (error) {
120b078ae7eSchs printf("NFS mount error=%d\n", errno);
12138c7f668Sgwr rootip.s_addr = 0;
12238c7f668Sgwr fail:
12338c7f668Sgwr netif_close(netdev_sock);
12438c7f668Sgwr netdev_sock = -1;
1251c038e68Sisaki return error;
1268e179d8eSgwr }
127d16aceedSgmcgarry #ifdef NETIF_DEBUG
12838c7f668Sgwr if (debug)
129db908184Smartin printf("NFS mount succeeded\n");
130d16aceedSgmcgarry #endif
13138c7f668Sgwr }
13238c7f668Sgwr }
13338c7f668Sgwr netdev_opens++;
1348e179d8eSgwr f->f_devdata = nfs_root_node;
1351c038e68Sisaki return error;
1368e179d8eSgwr }
1378e179d8eSgwr
1388e179d8eSgwr int
net_close(struct open_file * f)1391c038e68Sisaki net_close(struct open_file *f)
1408e179d8eSgwr {
14138c7f668Sgwr
14238c7f668Sgwr #ifdef NETIF_DEBUG
14338c7f668Sgwr if (debug)
14438c7f668Sgwr printf("net_close: opens=%d\n", netdev_opens);
14538c7f668Sgwr #endif
14638c7f668Sgwr
1478e179d8eSgwr /* On last close, do netif close, etc. */
1488e179d8eSgwr f->f_devdata = NULL;
14938c7f668Sgwr /* Extra close call? */
15038c7f668Sgwr if (netdev_opens <= 0)
1511c038e68Sisaki return 0;
15238c7f668Sgwr netdev_opens--;
15338c7f668Sgwr /* Not last close? */
15438c7f668Sgwr if (netdev_opens > 0)
1551c038e68Sisaki return 0;
15638c7f668Sgwr rootip.s_addr = 0;
15738c7f668Sgwr if (netdev_sock >= 0) {
158d16aceedSgmcgarry #ifdef NETIF_DEBUG
15938c7f668Sgwr if (debug)
160*10497fd2Schristos printf("%s: calling netif_close()\n", __func__);
161d16aceedSgmcgarry #endif
16238c7f668Sgwr netif_close(netdev_sock);
16338c7f668Sgwr netdev_sock = -1;
16438c7f668Sgwr }
1651c038e68Sisaki return 0;
1668e179d8eSgwr }
1678e179d8eSgwr
1688e179d8eSgwr int
net_ioctl(struct open_file * f,u_long cmd,void * data)1691c038e68Sisaki net_ioctl(struct open_file *f, u_long cmd, void *data)
1708e179d8eSgwr {
1711c038e68Sisaki
1728e179d8eSgwr return EIO;
1738e179d8eSgwr }
1748e179d8eSgwr
1758e179d8eSgwr int
net_strategy(void * devdata,int rw,daddr_t blk,size_t size,void * buf,size_t * rsize)1761c038e68Sisaki net_strategy(void *devdata, int rw, daddr_t blk, size_t size, void *buf,
1771c038e68Sisaki size_t *rsize)
1788e179d8eSgwr {
1791c038e68Sisaki
1808e179d8eSgwr return EIO;
1818e179d8eSgwr }
1828e179d8eSgwr
1832cf76130Sgwr
1848e179d8eSgwr /*
1858e179d8eSgwr * Get info for NFS boot: our IP address, our hostname,
1868e179d8eSgwr * server IP address, and our root path on the server.
1878e179d8eSgwr * There are two ways to do this: The old, Sun way,
1888e179d8eSgwr * and the more modern, BOOTP way. (RFC951, RFC1048)
1892cf76130Sgwr *
1902cf76130Sgwr * The default is to use the Sun bootparams RPC
1912cf76130Sgwr * (because that is what the kernel will do).
1922cf76130Sgwr * MD code can make try_bootp initialied data,
1932cf76130Sgwr * which will override this common definition.
1948e179d8eSgwr */
1952cf76130Sgwr #ifdef SUPPORT_BOOTP
1962cf76130Sgwr int try_bootp;
1972cf76130Sgwr #endif
1988e179d8eSgwr
1992cf76130Sgwr static int
net_getparams(int sock)2001c038e68Sisaki net_getparams(int sock)
2012cf76130Sgwr {
202ecd43c78Sgwr char buf[MAXHOSTNAMELEN];
203ecd43c78Sgwr n_long smask;
2042cf76130Sgwr
2052cf76130Sgwr #ifdef SUPPORT_BOOTP
2062cf76130Sgwr /*
2072cf76130Sgwr * Try to get boot info using BOOTP. If we succeed, then
2082cf76130Sgwr * the server IP address, gateway, and root path will all
2092cf76130Sgwr * be initialized. If any remain uninitialized, we will
2102cf76130Sgwr * use RARP and RPC/bootparam (the Sun way) to get them.
2112cf76130Sgwr */
212ecd43c78Sgwr if (try_bootp)
2132cf76130Sgwr bootp(sock);
214ecd43c78Sgwr if (myip.s_addr != 0)
2151c038e68Sisaki return 0;
216d16aceedSgmcgarry #ifdef NETIF_DEBUG
217ecd43c78Sgwr if (debug)
218db908184Smartin printf("BOOTP failed, trying RARP/RPC...\n");
2192cf76130Sgwr #endif
220d16aceedSgmcgarry #endif
2212cf76130Sgwr
222ecd43c78Sgwr /*
223ecd43c78Sgwr * Use RARP to get our IP address. This also sets our
224ecd43c78Sgwr * netmask to the "natural" default for our address.
225ecd43c78Sgwr */
22638c7f668Sgwr if (rarp_getipaddress(sock)) {
227db908184Smartin printf("RARP failed\n");
2281c038e68Sisaki return EIO;
22938c7f668Sgwr }
230db908184Smartin #ifdef NETIF_DEBUG
231db908184Smartin if (debug)
232db908184Smartin printf("client addr: %s\n", inet_ntoa(myip));
233db908184Smartin #endif
2348e179d8eSgwr
23523ee5602Sgwr /* Get our hostname, server IP address, gateway. */
23638c7f668Sgwr if (bp_whoami(sock)) {
237db908184Smartin printf("bootparam/whoami RPC failed\n");
2381c038e68Sisaki return EIO;
23938c7f668Sgwr }
240db908184Smartin #ifdef NETIF_DEBUG
241db908184Smartin if (debug)
242db908184Smartin printf("client name: %s\n", hostname);
243db908184Smartin #endif
244ecd43c78Sgwr
245ecd43c78Sgwr /*
246ecd43c78Sgwr * Ignore the gateway from whoami (unreliable).
247ecd43c78Sgwr * Use the "gateway" parameter instead.
248ecd43c78Sgwr */
249ecd43c78Sgwr smask = 0;
250ecd43c78Sgwr gateip.s_addr = 0;
2511c038e68Sisaki if (bp_getfile(sock, "gateway", &gateip, buf)) {
252*10497fd2Schristos printf("%s: gateway bootparam missing\n", __func__);
2531c038e68Sisaki } else {
254ecd43c78Sgwr /* Got it! Parse the netmask. */
255e6b49c78Sdrochner smask = inet_addr(buf);
2565afda96fSgwr }
2575afda96fSgwr if (smask) {
2582031003cSgwr netmask = smask;
259db908184Smartin #ifdef NETIF_DEBUG
260db908184Smartin if (debug)
261db908184Smartin printf("subnet mask: %s\n", intoa(netmask));
262db908184Smartin #endif
263d6335407Sgwr }
264db908184Smartin #ifdef NETIF_DEBUG
265db908184Smartin if (debug)
2665afda96fSgwr if (gateip.s_addr)
267db908184Smartin printf("net gateway: %s\n", inet_ntoa(gateip));
268db908184Smartin #endif
26923ee5602Sgwr
2702cf76130Sgwr /* Get the root server and pathname. */
27138c7f668Sgwr if (bp_getfile(sock, "root", &rootip, rootpath)) {
272db908184Smartin printf("bootparam/getfile RPC failed\n");
2731c038e68Sisaki return EIO;
27438c7f668Sgwr }
2758e179d8eSgwr
276db908184Smartin #ifdef NETIF_DEBUG
277db908184Smartin if (debug) {
278db908184Smartin printf("server addr: %s\n", inet_ntoa(rootip));
279db908184Smartin printf("server path: %s\n", rootpath);
280db908184Smartin }
281db908184Smartin #endif
2828e179d8eSgwr
2831c038e68Sisaki return 0;
2848e179d8eSgwr }
285