1 /*
2 * $NetBSD: dev_net.c,v 1.12 1997/12/10 20:38:37 gwr Exp $
3 */
4
5 /*-
6 * Copyright (c) 1997 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Gordon W. Ross.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD: src/sys/boot/common/dev_net.c,v 1.18 2008/09/10 20:53:22 marius Exp $");
43
44 /*-
45 * This module implements a "raw device" interface suitable for
46 * use by the stand-alone I/O library NFS code. This interface
47 * does not support any "block" access, and exists only for the
48 * purpose of initializing the network interface, getting boot
49 * parameters, and performing the NFS mount.
50 *
51 * At open time, this does:
52 *
53 * find interface - netif_open()
54 * RARP for IP address - rarp_getipaddress()
55 * RPC/bootparams - callrpc(d, RPC_BOOTPARAMS, ...)
56 * RPC/mountd - nfs_mount(sock, ip, path)
57 *
58 * the root file handle from mountd is saved in a global
59 * for use by the NFS open code (NFS/lookup).
60 */
61
62 #include <machine/stdarg.h>
63 #include <sys/param.h>
64 #include <sys/socket.h>
65 #include <net/if.h>
66 #include <netinet/in.h>
67 #include <netinet/in_systm.h>
68
69 #include <stand.h>
70 #include <string.h>
71 #include <net.h>
72 #include <netif.h>
73 #include <bootp.h>
74 #include <bootparam.h>
75
76 #include "dev_net.h"
77 #include "bootstrap.h"
78
79 int debug = 0;
80
81 static int netdev_sock = -1;
82 static int netdev_opens;
83
84 static int net_init(void);
85 static int net_open(struct open_file *, ...);
86 static int net_close(struct open_file *);
87 static int net_strategy();
88 static void net_print(int);
89
90 static int net_getparams(int sock);
91
92 struct devsw netdev = {
93 "net",
94 DEVT_NET,
95 net_init,
96 net_strategy,
97 net_open,
98 net_close,
99 noioctl,
100 net_print
101 };
102
103 int
104 net_init(void)
105 {
106
107 return (0);
108 }
109
110 /*
111 * Called by devopen after it sets f->f_dev to our devsw entry.
112 * This opens the low-level device and sets f->f_devdata.
113 * This is declared with variable arguments...
114 */
115 int
116 net_open(struct open_file *f, ...)
117 {
118 va_list args;
119 char *devname; /* Device part of file name (or NULL). */
120 int error = 0;
121
122 va_start(args, f);
123 devname = va_arg(args, char*);
124 va_end(args);
125
126 /* On first open, do netif open, mount, etc. */
127 if (netdev_opens == 0) {
128 /* Find network interface. */
129 if (netdev_sock < 0) {
130 netdev_sock = netif_open(devname);
131 if (netdev_sock < 0) {
132 printf("net_open: netif_open() failed\n");
133 return (ENXIO);
134 }
135 if (debug)
136 printf("net_open: netif_open() succeeded\n");
137 }
138 if (rootip.s_addr == 0) {
139 /* Get root IP address, and path, etc. */
140 error = net_getparams(netdev_sock);
141 if (error) {
142 /* getparams makes its own noise */
143 netif_close(netdev_sock);
144 netdev_sock = -1;
145 return (error);
146 }
147 }
148 #if defined(__sparc64__)
149 netdev_opens++;
150 #endif
151 }
152 netdev_opens++;
153 f->f_devdata = &netdev_sock;
154 return (error);
155 }
156
157 int
158 net_close(struct open_file *f)
159 {
160 #ifdef NETIF_DEBUG
161 if (debug)
162 printf("net_close: opens=%d\n", netdev_opens);
163 #endif
164
165 /* On last close, do netif close, etc. */
166 f->f_devdata = NULL;
167 /* Extra close call? */
168 if (netdev_opens <= 0)
169 return (0);
170 netdev_opens--;
171 /* Not last close? */
172 if (netdev_opens > 0)
173 return(0);
174 rootip.s_addr = 0;
175 if (netdev_sock >= 0) {
176 if (debug)
177 printf("net_close: calling netif_close()\n");
178 netif_close(netdev_sock);
179 netdev_sock = -1;
180 }
181 return (0);
182 }
183
184 int
185 net_strategy()
186 {
187
188 return (EIO);
189 }
190
191 #define SUPPORT_BOOTP
192
193 /*
194 * Get info for NFS boot: our IP address, our hostname,
195 * server IP address, and our root path on the server.
196 * There are two ways to do this: The old, Sun way,
197 * and the more modern, BOOTP way. (RFC951, RFC1048)
198 *
199 * The default is to use the Sun bootparams RPC
200 * (because that is what the kernel will do).
201 * MD code can make try_bootp initialied data,
202 * which will override this common definition.
203 */
204 #ifdef SUPPORT_BOOTP
205 int try_bootp = 1;
206 #endif
207
208 extern n_long ip_convertaddr(char *p);
209
210 static int
211 net_getparams(int sock)
212 {
213 char buf[MAXHOSTNAMELEN];
214 char temp[FNAME_SIZE];
215 struct iodesc *d;
216 int i;
217 n_long smask;
218
219 #ifdef SUPPORT_BOOTP
220 /*
221 * Try to get boot info using BOOTP. If we succeed, then
222 * the server IP address, gateway, and root path will all
223 * be initialized. If any remain uninitialized, we will
224 * use RARP and RPC/bootparam (the Sun way) to get them.
225 */
226 if (try_bootp)
227 bootp(sock, BOOTP_NONE);
228 if (myip.s_addr != 0)
229 goto exit;
230 if (debug)
231 printf("net_open: BOOTP failed, trying RARP/RPC...\n");
232 #endif
233
234 /*
235 * Use RARP to get our IP address. This also sets our
236 * netmask to the "natural" default for our address.
237 */
238 if (rarp_getipaddress(sock)) {
239 printf("net_open: RARP failed\n");
240 return (EIO);
241 }
242 printf("net_open: client addr: %s\n", inet_ntoa(myip));
243
244 /* Get our hostname, server IP address, gateway. */
245 if (bp_whoami(sock)) {
246 printf("net_open: bootparam/whoami RPC failed\n");
247 return (EIO);
248 }
249 if (debug)
250 printf("net_open: client name: %s\n", hostname);
251
252 /*
253 * Ignore the gateway from whoami (unreliable).
254 * Use the "gateway" parameter instead.
255 */
256 smask = 0;
257 gateip.s_addr = 0;
258 if (bp_getfile(sock, "gateway", &gateip, buf) == 0) {
259 /* Got it! Parse the netmask. */
260 smask = ip_convertaddr(buf);
261 }
262 if (smask) {
263 netmask = smask;
264 if (debug)
265 printf("net_open: subnet mask: %s\n", intoa(netmask));
266 }
267 if (gateip.s_addr && debug)
268 printf("net_open: net gateway: %s\n", inet_ntoa(gateip));
269
270 /* Get the root server and pathname. */
271 if (bp_getfile(sock, "root", &rootip, rootpath)) {
272 printf("net_open: bootparam/getfile RPC failed\n");
273 return (EIO);
274 }
275 exit:
276 /*
277 * If present, strip the server's address off of the rootpath
278 * before passing it along. This allows us to be compatible with
279 * the kernel's diskless (BOOTP_NFSROOT) booting conventions
280 */
281 for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++)
282 if (rootpath[i] == ':')
283 break;
284 if (i && i != FNAME_SIZE && rootpath[i] == ':') {
285 rootpath[i++] = '\0';
286 if (inet_addr(&rootpath[0]) != INADDR_NONE)
287 rootip.s_addr = inet_addr(&rootpath[0]);
288 bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1);
289 bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1);
290 }
291 if (debug) {
292 printf("net_open: server addr: %s\n", inet_ntoa(rootip));
293 printf("net_open: server path: %s\n", rootpath);
294 }
295
296 d = socktodesc(sock);
297 sprintf(temp, "%6D", d->myea, ":");
298 setenv("boot.netif.ip", inet_ntoa(myip), 1);
299 setenv("boot.netif.netmask", intoa(netmask), 1);
300 setenv("boot.netif.gateway", inet_ntoa(gateip), 1);
301 setenv("boot.netif.hwaddr", temp, 1);
302 setenv("boot.nfsroot.server", inet_ntoa(rootip), 1);
303 setenv("boot.nfsroot.path", rootpath, 1);
304
305 return (0);
306 }
307
308 static void
309 net_print(int verbose)
310 {
311 struct netif_driver *drv;
312 int i, d, cnt;
313
314 cnt = 0;
315 for (d = 0; netif_drivers[d]; d++) {
316 drv = netif_drivers[d];
317 for (i = 0; i < drv->netif_nifs; i++) {
318 printf("\t%s%d:", "net", cnt++);
319 if (verbose)
320 printf(" (%s%d)", drv->netif_bname,
321 drv->netif_ifs[i].dif_unit);
322 }
323 }
324 printf("\n");
325 }
326 Cache object: f0dabfbce6d9e753bae760f03a349462
|