xref: /netbsd-src/sys/arch/i386/stand/efiboot/dev_net.c (revision fcd0bf31a0548706309f86fd396cfc7cce6348d1)
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
net_open(struct open_file * f,...)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
net_close(struct open_file * f)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
net_ioctl(struct open_file * f,u_long cmd,void * data)152 net_ioctl(struct open_file *f, u_long cmd, void *data)
153 {
154 
155 	return EIO;
156 }
157 
158 int
net_strategy(void * devdata,int rw,daddr_t blk,size_t size,void * buf,size_t * rsize)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
net_getparams(int sock)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