This source file includes following definitions.
- nfs_boot_init
- nfs_boot_getfh
- nfs_boot_init
- nfs_boot_getfh
- bp_whoami
- bp_getfile
- md_mount
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/conf.h>
35 #include <sys/ioctl.h>
36 #include <sys/proc.h>
37 #include <sys/mount.h>
38 #include <sys/mbuf.h>
39 #include <sys/reboot.h>
40 #include <sys/socket.h>
41 #include <sys/socketvar.h>
42
43 #include <net/if.h>
44 #include <net/route.h>
45
46 #include <netinet/in.h>
47 #include <netinet/if_ether.h>
48
49 #include <nfs/rpcv2.h>
50 #include <nfs/nfsproto.h>
51 #include <nfs/nfs.h>
52 #include <nfs/nfsdiskless.h>
53 #include <nfs/krpc.h>
54 #include <nfs/xdr_subs.h>
55 #include <nfs/nfs_var.h>
56
57 #include "ether.h"
58
59 #if !defined(NFSCLIENT) || (NETHER == 0 && NFDDI == 0)
60
61 int
62 nfs_boot_init(nd, procp)
63 struct nfs_diskless *nd;
64 struct proc *procp;
65 {
66 panic("nfs_boot_init: NFSCLIENT not enabled in kernel");
67 }
68
69 int
70 nfs_boot_getfh(bpsin, key, ndmntp, retries)
71 struct sockaddr_in *bpsin;
72 char *key;
73 struct nfs_dlmount *ndmntp;
74 int retries;
75 {
76
77 return (EOPNOTSUPP);
78 }
79
80 #else
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103 static int bp_whoami(struct sockaddr_in *bpsin,
104 struct in_addr *my_ip, struct in_addr *gw_ip);
105 static int bp_getfile(struct sockaddr_in *bpsin, char *key,
106 struct sockaddr_in *mdsin, char *servname, char *path, int retries);
107
108
109 static int md_mount(struct sockaddr_in *mdsin, char *path,
110 u_char *fh);
111
112 char *nfsbootdevname;
113
114
115
116
117 int
118 nfs_boot_init(nd, procp)
119 struct nfs_diskless *nd;
120 struct proc *procp;
121 {
122 struct ifreq ireq;
123 struct in_addr my_ip, gw_ip;
124 struct sockaddr_in bp_sin;
125 struct sockaddr_in *sin;
126 struct ifnet *ifp;
127 struct socket *so;
128 int error;
129
130
131
132
133
134
135
136
137
138
139
140
141
142 if (nfsbootdevname)
143 ifp = ifunit(nfsbootdevname);
144 else {
145 for (ifp = TAILQ_FIRST(&ifnet); ifp != NULL;
146 ifp = TAILQ_NEXT(ifp, if_list)) {
147 if ((ifp->if_flags &
148 (IFF_LOOPBACK|IFF_POINTOPOINT)) == 0)
149 break;
150 }
151 }
152 if (ifp == NULL)
153 panic("nfs_boot: no suitable interface");
154 bcopy(ifp->if_xname, ireq.ifr_name, IFNAMSIZ);
155 printf("nfs_boot: using interface %s, with revarp & bootparams\n",
156 ireq.ifr_name);
157
158
159
160
161
162
163
164 if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0)) != 0)
165 panic("nfs_boot: socreate, error=%d", error);
166 error = ifioctl(so, SIOCGIFFLAGS, (caddr_t)&ireq, procp);
167 if (error)
168 panic("nfs_boot: GIFFLAGS, error=%d", error);
169 ireq.ifr_flags |= IFF_UP;
170 error = ifioctl(so, SIOCSIFFLAGS, (caddr_t)&ireq, procp);
171 if (error)
172 panic("nfs_boot: SIFFLAGS, error=%d", error);
173
174
175
176
177 if ((error = revarpwhoami(&my_ip, ifp)) != 0)
178 panic("revarp failed, error=%d", error);
179 printf("nfs_boot: client_addr=%s\n", inet_ntoa(my_ip));
180
181
182
183
184
185 sin = (struct sockaddr_in *)&ireq.ifr_addr;
186 bzero((caddr_t)sin, sizeof(*sin));
187 sin->sin_len = sizeof(*sin);
188 sin->sin_family = AF_INET;
189 sin->sin_addr.s_addr = my_ip.s_addr;
190 error = ifioctl(so, SIOCSIFADDR, (caddr_t)&ireq, procp);
191 if (error)
192 panic("nfs_boot: set if addr, error=%d", error);
193
194 soclose(so);
195
196
197
198
199
200
201
202
203
204 bzero((caddr_t)&bp_sin, sizeof(bp_sin));
205 bp_sin.sin_len = sizeof(bp_sin);
206 bp_sin.sin_family = AF_INET;
207 bp_sin.sin_addr.s_addr = INADDR_BROADCAST;
208 hostnamelen = MAXHOSTNAMELEN;
209
210
211 error = bp_whoami(&bp_sin, &my_ip, &gw_ip);
212 if (error)
213 panic("nfs_boot: bootparam whoami, error=%d", error);
214 printf("nfs_boot: server_addr=%s hostname=%s\n",
215 inet_ntoa(bp_sin.sin_addr), hostname);
216
217 #ifdef NFS_BOOT_GATEWAY
218
219
220
221
222
223
224
225
226
227
228
229
230
231 if (gw_ip.s_addr) {
232 struct sockaddr dst, gw, mask;
233
234 bzero((caddr_t)&dst, sizeof(dst));
235 dst.sa_len = sizeof(dst);
236 dst.sa_family = AF_INET;
237
238 bzero((caddr_t)&gw, sizeof(gw));
239 sin = (struct sockaddr_in *)&gw;
240 sin->sin_len = sizeof(gw);
241 sin->sin_family = AF_INET;
242 sin->sin_addr.s_addr = gw_ip.s_addr;
243
244 bzero(&mask, sizeof(mask));
245
246 printf("nfs_boot: gateway=%s\n", inet_ntoa(gw_ip));
247
248 error = rtrequest(RTM_ADD, &dst, (struct sockaddr *)&gw,
249 &mask, (RTF_UP | RTF_GATEWAY | RTF_STATIC), NULL, 0);
250 if (error)
251 printf("nfs_boot: add route, error=%d\n", error);
252 }
253 #endif
254
255 bcopy(&bp_sin, &nd->nd_boot, sizeof(bp_sin));
256
257 return (0);
258 }
259
260 int
261 nfs_boot_getfh(bpsin, key, ndmntp, retries)
262 struct sockaddr_in *bpsin;
263 char *key;
264 struct nfs_dlmount *ndmntp;
265 int retries;
266 {
267 char pathname[MAXPATHLEN];
268 char *sp, *dp, *endp;
269 struct sockaddr_in *sin;
270 int error;
271
272 sin = &ndmntp->ndm_saddr;
273
274
275
276
277
278 error = bp_getfile(bpsin, key, sin, ndmntp->ndm_host, pathname,
279 retries);
280 if (error) {
281 printf("nfs_boot: bootparam get %s: %d\n", key, error);
282 return (error);
283 }
284
285
286
287
288
289 error = md_mount(sin, pathname, ndmntp->ndm_fh);
290 if (error) {
291 printf("nfs_boot: mountd %s, error=%d\n", key, error);
292 return (error);
293 }
294
295
296
297 error = krpc_portmap(sin, NFS_PROG, NFS_VER2, &sin->sin_port);
298 if (error) {
299 printf("nfs_boot: portmap NFS/v2, error=%d\n", error);
300 return (error);
301 }
302
303
304 dp = ndmntp->ndm_host;
305 endp = dp + MNAMELEN - 1;
306 dp += strlen(dp);
307 *dp++ = ':';
308 for (sp = pathname; *sp && dp < endp;)
309 *dp++ = *sp++;
310 *dp = '\0';
311
312 return (0);
313 }
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 static int
332 bp_whoami(bpsin, my_ip, gw_ip)
333 struct sockaddr_in *bpsin;
334 struct in_addr *my_ip;
335 struct in_addr *gw_ip;
336 {
337
338 struct whoami_call {
339 u_int32_t call_prog;
340 u_int32_t call_vers;
341 u_int32_t call_proc;
342 u_int32_t call_arglen;
343 } *call;
344 struct callit_reply {
345 u_int32_t port;
346 u_int32_t encap_len;
347
348 } *reply;
349
350 struct mbuf *m, *from;
351 struct sockaddr_in *sin;
352 int error, msg_len;
353 int16_t port;
354
355
356
357
358 m = m_get(M_WAIT, MT_DATA);
359 call = mtod(m, struct whoami_call *);
360 m->m_len = sizeof(*call);
361 call->call_prog = txdr_unsigned(BOOTPARAM_PROG);
362 call->call_vers = txdr_unsigned(BOOTPARAM_VERS);
363 call->call_proc = txdr_unsigned(BOOTPARAM_WHOAMI);
364
365
366
367
368 m->m_next = xdr_inaddr_encode(my_ip);
369 call->call_arglen = txdr_unsigned(m->m_next->m_len);
370
371
372 bpsin->sin_port = htons(PMAPPORT);
373 from = NULL;
374 error = krpc_call(bpsin, PMAPPROG, PMAPVERS,
375 PMAPPROC_CALLIT, &m, &from, -1);
376 if (error)
377 return error;
378
379
380
381
382 if (m->m_len < sizeof(*reply)) {
383 m = m_pullup(m, sizeof(*reply));
384 if (m == NULL)
385 goto bad;
386 }
387 reply = mtod(m, struct callit_reply *);
388 port = fxdr_unsigned(u_int32_t, reply->port);
389 msg_len = fxdr_unsigned(u_int32_t, reply->encap_len);
390 m_adj(m, sizeof(*reply));
391
392
393
394
395 sin = mtod(from, struct sockaddr_in *);
396 bpsin->sin_port = htons(port);
397 bpsin->sin_addr.s_addr = sin->sin_addr.s_addr;
398
399
400 hostnamelen = MAXHOSTNAMELEN-1;
401 m = xdr_string_decode(m, hostname, &hostnamelen);
402 if (m == NULL)
403 goto bad;
404
405
406 domainnamelen = MAXHOSTNAMELEN-1;
407 m = xdr_string_decode(m, domainname, &domainnamelen);
408 if (m == NULL)
409 goto bad;
410
411
412 m = xdr_inaddr_decode(m, gw_ip);
413 if (m == NULL)
414 goto bad;
415
416
417 goto out;
418
419 bad:
420 printf("nfs_boot: bootparam_whoami: bad reply\n");
421 error = EBADRPC;
422
423 out:
424 if (from)
425 m_freem(from);
426 if (m)
427 m_freem(m);
428 return(error);
429 }
430
431
432
433
434
435
436
437
438
439 static int
440 bp_getfile(bpsin, key, md_sin, serv_name, pathname, retries)
441 struct sockaddr_in *bpsin;
442 char *key;
443 struct sockaddr_in *md_sin;
444 char *serv_name;
445 char *pathname;
446 int retries;
447 {
448 struct mbuf *m;
449 struct sockaddr_in *sin;
450 struct in_addr inaddr;
451 int error, sn_len, path_len;
452
453
454
455
456
457
458 m = xdr_string_encode(hostname, hostnamelen);
459 if (m == NULL)
460 return (ENOMEM);
461
462
463 m->m_next = xdr_string_encode(key, strlen(key));
464 if (m->m_next == NULL)
465 return (ENOMEM);
466
467
468 error = krpc_call(bpsin, BOOTPARAM_PROG, BOOTPARAM_VERS,
469 BOOTPARAM_GETFILE, &m, NULL, retries);
470 if (error)
471 return error;
472
473
474
475
476
477
478 sn_len = MNAMELEN-1;
479 m = xdr_string_decode(m, serv_name, &sn_len);
480 if (m == NULL)
481 goto bad;
482
483
484 m = xdr_inaddr_decode(m, &inaddr);
485 if (m == NULL)
486 goto bad;
487
488
489 path_len = MAXPATHLEN-1;
490 m = xdr_string_decode(m, pathname, &path_len);
491 if (m == NULL)
492 goto bad;
493
494
495 sin = md_sin;
496 bzero((caddr_t)sin, sizeof(*sin));
497 sin->sin_len = sizeof(*sin);
498 sin->sin_family = AF_INET;
499 sin->sin_addr = inaddr;
500
501
502 goto out;
503
504 bad:
505 printf("nfs_boot: bootparam_getfile: bad reply\n");
506 error = EBADRPC;
507
508 out:
509 m_freem(m);
510 return(0);
511 }
512
513
514
515
516
517
518
519 static int
520 md_mount(mdsin, path, fhp)
521 struct sockaddr_in *mdsin;
522 char *path;
523 u_char *fhp;
524 {
525
526 struct rdata {
527 u_int32_t errno;
528 u_int8_t fh[NFSX_V2FH];
529 } *rdata;
530 struct mbuf *m;
531 int error;
532
533
534 error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
535 &mdsin->sin_port);
536 if (error) return error;
537
538 m = xdr_string_encode(path, strlen(path));
539 if (m == NULL)
540 return ENOMEM;
541
542
543 error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
544 RPCMNT_MOUNT, &m, NULL, -1);
545 if (error)
546 return error;
547
548
549 if (m->m_len < 4)
550 goto bad;
551
552 rdata = mtod(m, struct rdata *);
553 error = fxdr_unsigned(u_int32_t, rdata->errno);
554 if (error)
555 goto out;
556
557
558 if (m->m_len < sizeof(*rdata)) {
559 m = m_pullup(m, sizeof(*rdata));
560 if (m == NULL)
561 goto bad;
562 rdata = mtod(m, struct rdata *);
563 }
564 bcopy(rdata->fh, fhp, NFSX_V2FH);
565 goto out;
566
567 bad:
568 error = EBADRPC;
569
570 out:
571 m_freem(m);
572 return error;
573 }
574
575 #endif