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