1*6adfa96cSmrg /* $NetBSD: net.c,v 1.10 2021/04/12 03:55:41 mrg Exp $ */
2e144281cSmrg
3e144281cSmrg /*
4e144281cSmrg * Copyright (C) 1995 Wolfgang Solfrank.
5e144281cSmrg * Copyright (C) 1995 TooLs GmbH.
6e144281cSmrg * All rights reserved.
7e144281cSmrg *
8e144281cSmrg * Redistribution and use in source and binary forms, with or without
9e144281cSmrg * modification, are permitted provided that the following conditions
10e144281cSmrg * are met:
11e144281cSmrg * 1. Redistributions of source code must retain the above copyright
12e144281cSmrg * notice, this list of conditions and the following disclaimer.
13e144281cSmrg * 2. Redistributions in binary form must reproduce the above copyright
14e144281cSmrg * notice, this list of conditions and the following disclaimer in the
15e144281cSmrg * documentation and/or other materials provided with the distribution.
16e144281cSmrg * 3. All advertising materials mentioning features or use of this software
17e144281cSmrg * must display the following acknowledgement:
18e144281cSmrg * This product includes software developed by TooLs GmbH.
19e144281cSmrg * 4. The name of TooLs GmbH may not be used to endorse or promote products
20e144281cSmrg * derived from this software without specific prior written permission.
21e144281cSmrg *
22e144281cSmrg * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23e144281cSmrg * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24e144281cSmrg * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25e144281cSmrg * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26e144281cSmrg * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27e144281cSmrg * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28e144281cSmrg * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29e144281cSmrg * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30e144281cSmrg * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31e144281cSmrg * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32e144281cSmrg */
33e144281cSmrg
34e144281cSmrg /*
35e144281cSmrg * This module implements a "raw device" interface suitable for
36e144281cSmrg * use by the stand-alone I/O library NFS code. This interface
37e144281cSmrg * does not support any "block" access, and exists only for the
38e144281cSmrg * purpose of initializing the network interface, getting boot
39e144281cSmrg * parameters, and performing the NFS mount.
40e144281cSmrg *
41e144281cSmrg * At open time, this does:
42e144281cSmrg *
43e144281cSmrg * find interface - netif_open()
44e144281cSmrg * BOOTP - bootp()
45e144281cSmrg * RPC/mountd - nfs_mount()
46e144281cSmrg *
47e144281cSmrg * The root file handle from mountd is saved in a global
48e144281cSmrg * for use by the NFS open code (NFS/lookup).
49e144281cSmrg *
50e144281cSmrg * Note: this is based in part on sys/arch/sparc/stand/net.c
51e144281cSmrg */
52e144281cSmrg
53e144281cSmrg #include <sys/param.h>
54e144281cSmrg #include <sys/socket.h>
55e144281cSmrg
56e144281cSmrg #include <net/if.h>
57e144281cSmrg #include <netinet/in.h>
58e144281cSmrg #include <netinet/in_systm.h>
59e144281cSmrg
60e144281cSmrg #include <lib/libsa/stand.h>
61e144281cSmrg #include <lib/libsa/net.h>
62e144281cSmrg #include <lib/libsa/netif.h>
63c95f237aStsutsui #include <lib/libsa/bootp.h>
64fa20324cSchristos #include <lib/libsa/bootparam.h>
65fa20324cSchristos #include <lib/libsa/nfs.h>
66e144281cSmrg
67e144281cSmrg #include <lib/libkern/libkern.h>
68e144281cSmrg
694c3c91e6Suwe #include "ofdev.h"
70c95f237aStsutsui #include "net.h"
714c3c91e6Suwe
724c3c91e6Suwe
734c3c91e6Suwe static int net_mountroot_bootparams(void);
744c3c91e6Suwe static int net_mountroot_bootp(void);
75e144281cSmrg
76e144281cSmrg static int netdev_sock = -1;
77e144281cSmrg static int open_count;
78e144281cSmrg
79e144281cSmrg /*
80e144281cSmrg * Called by devopen after it sets f->f_dev to our devsw entry.
81e144281cSmrg * This opens the low-level device and sets f->f_devdata.
82e144281cSmrg */
83e144281cSmrg int
net_open(struct of_dev * op)844c3c91e6Suwe net_open(struct of_dev *op)
85e144281cSmrg {
86e144281cSmrg int error = 0;
87e144281cSmrg
88e144281cSmrg /*
89e144281cSmrg * On first open, do netif open, mount, etc.
90e144281cSmrg */
91e144281cSmrg if (open_count == 0) {
92e144281cSmrg /* Find network interface. */
93e144281cSmrg if ((netdev_sock = netif_open(op)) < 0) {
94e144281cSmrg error = errno;
95e144281cSmrg goto bad;
96e144281cSmrg }
97e144281cSmrg }
98e144281cSmrg open_count++;
99e144281cSmrg bad:
100e144281cSmrg if (netdev_sock >= 0 && open_count == 0) {
101e144281cSmrg netif_close(netdev_sock);
102e144281cSmrg netdev_sock = -1;
103e144281cSmrg }
104e144281cSmrg return error;
105e144281cSmrg }
106e144281cSmrg
107e144281cSmrg int
net_close(struct of_dev * op)1084c3c91e6Suwe net_close(struct of_dev *op)
109e144281cSmrg {
1104c3c91e6Suwe
111e144281cSmrg /*
112e144281cSmrg * On last close, do netif close, etc.
113e144281cSmrg */
114e144281cSmrg if (open_count > 0)
115e144281cSmrg if (--open_count == 0) {
116e144281cSmrg netif_close(netdev_sock);
117e144281cSmrg netdev_sock = -1;
118e144281cSmrg }
119c95f237aStsutsui return 0;
120e144281cSmrg }
121e144281cSmrg
122b49ed2c0Sroy static void
net_clear_params(void)123b49ed2c0Sroy net_clear_params(void)
124b49ed2c0Sroy {
125b49ed2c0Sroy
126b49ed2c0Sroy myip.s_addr = 0;
127b49ed2c0Sroy netmask = 0;
128b49ed2c0Sroy gateip.s_addr = 0;
129b49ed2c0Sroy *hostname = '\0';
130b49ed2c0Sroy rootip.s_addr = 0;
131b49ed2c0Sroy *rootpath = '\0';
132b49ed2c0Sroy }
133b49ed2c0Sroy
134e144281cSmrg int
net_mountroot_bootparams(void)1354c3c91e6Suwe net_mountroot_bootparams(void)
136e144281cSmrg {
1374c3c91e6Suwe
138b49ed2c0Sroy net_clear_params();
139b49ed2c0Sroy
140e144281cSmrg /* Get our IP address. (rarp.c) */
141e144281cSmrg if (rarp_getipaddress(netdev_sock) == -1)
142e144281cSmrg return (errno);
143b49ed2c0Sroy printf("Using BOOTPARAMS protocol:\n ip addr=%s\n", inet_ntoa(myip));
144e144281cSmrg if (bp_whoami(netdev_sock))
145e144281cSmrg return (errno);
146b49ed2c0Sroy printf(" hostname=%s\n", hostname);
147e144281cSmrg if (bp_getfile(netdev_sock, "root", &rootip, rootpath))
148e144281cSmrg return (errno);
149e144281cSmrg
150e144281cSmrg return (0);
151e144281cSmrg }
152e144281cSmrg
153e144281cSmrg int
net_mountroot_bootp(void)1544c3c91e6Suwe net_mountroot_bootp(void)
155e144281cSmrg {
156b49ed2c0Sroy int attempts;
1574c3c91e6Suwe
158b49ed2c0Sroy /* We need a few attempts here as some DHCP servers
159b49ed2c0Sroy * require >1 packet and my wireless bridge is always
160b49ed2c0Sroy * in learning mode until the 2nd attempt ... */
161b49ed2c0Sroy for (attempts = 0; attempts < 3; attempts++) {
162b49ed2c0Sroy net_clear_params();
163e144281cSmrg bootp(netdev_sock);
164b49ed2c0Sroy if (myip.s_addr != 0)
165b49ed2c0Sroy break;
166b49ed2c0Sroy }
167e144281cSmrg if (myip.s_addr == 0)
168e144281cSmrg return(ENOENT);
169e144281cSmrg
170b49ed2c0Sroy printf("Using BOOTP protocol:\n ip addr=%s\n", inet_ntoa(myip));
171e144281cSmrg if (hostname[0])
172b49ed2c0Sroy printf(" hostname=%s\n", hostname);
173e144281cSmrg if (netmask)
174b49ed2c0Sroy printf(" netmask=%s\n", intoa(netmask));
175e144281cSmrg if (gateip.s_addr)
176b49ed2c0Sroy printf(" gateway=%s\n", inet_ntoa(gateip));
177e144281cSmrg
178e144281cSmrg return (0);
179e144281cSmrg }
180e144281cSmrg
1818aa95513Stsutsui /*
1828aa95513Stsutsui * libsa's tftp_open expects a pointer to netdev_sock, i.e. an (int *),
1838aa95513Stsutsui * in f_devdata, a pointer to which gets handed down from devopen().
1848aa95513Stsutsui *
1858aa95513Stsutsui * Do not expect booting via different methods to have the same
1868aa95513Stsutsui * requirements or semantics.
1878aa95513Stsutsui *
1888aa95513Stsutsui * net_tftp_bootp uses net_mountroot_bootp because that incidentially does
1898aa95513Stsutsui * most of what it needs to do. It of course in no manner actually mounts
1908aa95513Stsutsui * anything, all that routine actually does is prepare the socket for the
1918aa95513Stsutsui * necessary net access, and print info for the user.
1928aa95513Stsutsui */
1938aa95513Stsutsui
194e144281cSmrg int
net_tftp_bootp(int ** sock)1958aa95513Stsutsui net_tftp_bootp(int **sock)
19617740d28Smlelstv {
19717740d28Smlelstv
198b49ed2c0Sroy net_mountroot_bootp();
19917740d28Smlelstv if (myip.s_addr == 0)
20017740d28Smlelstv return(ENOENT);
20117740d28Smlelstv
2028aa95513Stsutsui *sock = &netdev_sock;
20317740d28Smlelstv return (0);
20417740d28Smlelstv }
20517740d28Smlelstv
20617740d28Smlelstv int
net_mountroot(void)2074c3c91e6Suwe net_mountroot(void)
208e144281cSmrg {
209e144281cSmrg int error;
210e144281cSmrg
211e144281cSmrg #ifdef DEBUG
212e144281cSmrg printf("net_mountroot\n");
213e144281cSmrg #endif
214e144281cSmrg
215e144281cSmrg /*
216e144281cSmrg * Get info for NFS boot: our IP address, our hostname,
217e144281cSmrg * server IP address, and our root path on the server.
218e144281cSmrg * There are two ways to do this: The old, Sun way,
219e144281cSmrg * and the more modern, BOOTP way. (RFC951, RFC1048)
220e144281cSmrg */
221e144281cSmrg
222aaa7dba0Slukem /* Try BOOTP first */
223e144281cSmrg error = net_mountroot_bootp();
224aaa7dba0Slukem /* Historically, we've used BOOTPARAMS, so try that next */
225aaa7dba0Slukem if (error != 0)
226aaa7dba0Slukem error = net_mountroot_bootparams();
227e144281cSmrg if (error != 0)
228e144281cSmrg return (error);
229e144281cSmrg
230b49ed2c0Sroy printf(" root addr=%s\n path=%s\n", inet_ntoa(rootip), rootpath);
231e144281cSmrg
232e144281cSmrg /* Get the NFS file handle (mount). */
233e144281cSmrg if (nfs_mount(netdev_sock, rootip, rootpath) != 0)
234e144281cSmrg return (errno);
235e144281cSmrg
236e144281cSmrg return (0);
237e144281cSmrg }
238