Print this page
*** NO COMMENTS ***
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fs.d/nfs/mount/mount.c
+++ new/usr/src/cmd/fs.d/nfs/mount/mount.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 27 /* All Rights Reserved */
28 28
29 29 /*
30 30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 31 * The Regents of the University of California
32 32 * All Rights Reserved
33 33 *
34 34 * University Acknowledgment- Portions of this document are derived from
35 35 * software developed by the University of California, Berkeley, and its
36 36 * contributors.
37 37 */
38 38
39 39 #pragma ident "%Z%%M% %I% %E% SMI"
40 40
41 41 /*
42 42 * nfs mount
43 43 */
44 44
45 45 #define NFSCLIENT
46 46 #include <locale.h>
47 47 #include <stdio.h>
48 48 #include <string.h>
49 49 #include <memory.h>
50 50 #include <stdarg.h>
51 51 #include <unistd.h>
52 52 #include <ctype.h>
53 53 #include <stdlib.h>
54 54 #include <signal.h>
55 55 #include <sys/param.h>
56 56 #include <rpc/rpc.h>
57 57 #include <errno.h>
58 58 #include <sys/stat.h>
59 59 #include <netdb.h>
60 60 #include <sys/mount.h>
61 61 #include <sys/mntent.h>
62 62 #include <sys/mnttab.h>
63 63 #include <nfs/nfs.h>
64 64 #include <nfs/mount.h>
65 65 #include <rpcsvc/mount.h>
66 66 #include <sys/pathconf.h>
67 67 #include <netdir.h>
68 68 #include <netconfig.h>
69 69 #include <sys/sockio.h>
70 70 #include <net/if.h>
71 71 #include <syslog.h>
72 72 #include <fslib.h>
73 73 #include <deflt.h>
74 74 #include <sys/wait.h>
75 75 #include "replica.h"
76 76 #include <netinet/in.h>
77 77 #include <nfs/nfs_sec.h>
78 78 #include <rpcsvc/daemon_utils.h>
79 79 #include <priv.h>
80 80 #include <tsol/label.h>
81 81 #include "nfs_subr.h"
82 82 #include "webnfs.h"
83 83 #include <rpcsvc/nfs4_prot.h>
84 84
85 85 #ifndef NFS_VERSMAX
86 86 #define NFS_VERSMAX 4
87 87 #endif
88 88 #ifndef NFS_VERSMIN
89 89 #define NFS_VERSMIN 2
90 90 #endif
91 91
92 92 #define RET_OK 0
93 93 #define RET_RETRY 32
94 94 #define RET_ERR 33
95 95 #define RET_MNTERR 1000
96 96 #define ERR_PROTO_NONE 0
97 97 #define ERR_PROTO_INVALID 901
98 98 #define ERR_PROTO_UNSUPP 902
99 99 #define ERR_NETPATH 903
100 100 #define ERR_NOHOST 904
101 101 #define ERR_RPCERROR 905
102 102
103 103 typedef struct err_ret {
104 104 int error_type;
105 105 int error_value;
106 106 } err_ret_t;
107 107
108 108 #define SET_ERR_RET(errst, etype, eval) \
109 109 if (errst) { \
110 110 (errst)->error_type = etype; \
111 111 (errst)->error_value = eval; \
112 112 }
113 113
114 114 /* number of transports to try */
115 115 #define MNT_PREF_LISTLEN 2
116 116 #define FIRST_TRY 1
117 117 #define SECOND_TRY 2
↓ open down ↓ |
117 lines elided |
↑ open up ↑ |
118 118
119 119 #define BIGRETRY 10000
120 120
121 121 /* maximum length of RPC header for NFS messages */
122 122 #define NFS_RPC_HDR 432
123 123
124 124 #define NFS_ARGS_EXTB_secdata(args, secdata) \
125 125 { (args)->nfs_args_ext = NFS_ARGS_EXTB, \
126 126 (args)->nfs_ext_u.nfs_extB.secdata = secdata; }
127 127
128 -extern int __clnt_bindresvport();
128 +extern int __clnt_bindresvport(CLIENT *);
129 129 extern char *nfs_get_qop_name();
130 130 extern AUTH * nfs_create_ah();
131 131 extern enum snego_stat nfs_sec_nego();
132 132
133 133 static void usage(void);
134 134 static int retry(struct mnttab *, int);
135 135 static int set_args(int *, struct nfs_args *, char *, struct mnttab *);
136 136 static int get_fh_via_pub(struct nfs_args *, char *, char *, bool_t, bool_t,
137 137 int *, struct netconfig **, ushort_t);
138 138 static int get_fh(struct nfs_args *, char *, char *, int *, bool_t,
139 139 struct netconfig **, ushort_t);
140 140 static int make_secure(struct nfs_args *, char *, struct netconfig *,
141 141 bool_t, rpcvers_t);
142 142 static int mount_nfs(struct mnttab *, int, err_ret_t *);
143 143 static int getaddr_nfs(struct nfs_args *, char *, struct netconfig **,
144 144 bool_t, char *, ushort_t, err_ret_t *, bool_t);
145 145 static void pr_err(const char *fmt, ...);
146 146 static void usage(void);
147 147 static struct netbuf *get_addr(char *, rpcprog_t, rpcvers_t,
148 148 struct netconfig **, char *, ushort_t, struct t_info *,
149 149 caddr_t *, bool_t, char *, err_ret_t *);
150 150
151 151 static struct netbuf *get_the_addr(char *, rpcprog_t, rpcvers_t,
152 152 struct netconfig *, ushort_t, struct t_info *, caddr_t *,
153 153 bool_t, char *, err_ret_t *);
154 154
155 155 extern int self_check(char *);
156 156
157 157 static void read_default(void);
158 158
159 159 static char typename[64];
160 160
161 161 static int bg = 0;
162 162 static int backgrounded = 0;
163 163 static int posix = 0;
164 164 static int retries = BIGRETRY;
165 165 static ushort_t nfs_port = 0;
166 166 static char *nfs_proto = NULL;
167 167
168 168 static int mflg = 0;
169 169 static int Oflg = 0; /* Overlay mounts */
170 170 static int qflg = 0; /* quiet - don't print warnings on bad options */
171 171
172 172 static char *fstype = MNTTYPE_NFS;
173 173
174 174 static seconfig_t nfs_sec;
175 175 static int sec_opt = 0; /* any security option ? */
176 176 static bool_t snego_done;
177 177 static void sigusr1(int);
178 178
179 179 /*
180 180 * list of support services needed
181 181 */
182 182 static char *service_list[] = { STATD, LOCKD, NULL };
183 183 static char *service_list_v4[] = { STATD, LOCKD, NFS4CBD, NFSMAPID, NULL };
184 184
185 185 /*
186 186 * These two variables control the NFS version number to be used.
187 187 *
188 188 * nfsvers defaults to 0 which means to use the highest number that
189 189 * both the client and the server support. It can also be set to
190 190 * a particular value, either 2, 3, or 4 to indicate the version
191 191 * number of choice. If the server (or the client) do not support
192 192 * the version indicated, then the mount attempt will be failed.
193 193 *
194 194 * nfsvers_to_use is the actual version number found to use. It
195 195 * is determined in get_fh by pinging the various versions of the
196 196 * NFS service on the server to see which responds positively.
197 197 *
198 198 * nfsretry_vers is the version number set when we retry the mount
199 199 * command with the version decremented from nfsvers_to_use.
200 200 * nfsretry_vers is set from nfsvers_to_use when we retry the mount
201 201 * for errors other than RPC errors; it helps un know why we are
202 202 * retrying. It is an indication that the retry is due to
203 203 * non-RPC errors.
204 204 */
205 205 static rpcvers_t nfsvers = 0;
206 206 static rpcvers_t nfsvers_to_use = 0;
207 207 static rpcvers_t nfsretry_vers = 0;
208 208
209 209 /*
210 210 * There are the defaults (range) for the client when determining
211 211 * which NFS version to use when probing the server (see above).
212 212 * These will only be used when the vers mount option is not used and
213 213 * these may be reset if /etc/default/nfs is configured to do so.
214 214 */
215 215 static rpcvers_t vers_max_default = NFS_VERSMAX_DEFAULT;
216 216 static rpcvers_t vers_min_default = NFS_VERSMIN_DEFAULT;
217 217
218 218 /*
219 219 * This variable controls whether to try the public file handle.
220 220 */
221 221 static bool_t public_opt;
222 222
223 223 int
224 224 main(int argc, char *argv[])
225 225 {
226 226 struct mnttab mnt;
227 227 extern char *optarg;
228 228 extern int optind;
229 229 char optbuf[MAX_MNTOPT_STR];
230 230 int ro = 0;
231 231 int r;
232 232 int c;
233 233 char *myname;
234 234 err_ret_t retry_error;
235 235
236 236 (void) setlocale(LC_ALL, "");
237 237 #if !defined(TEXT_DOMAIN)
238 238 #define TEXT_DOMAIN "SYS_TEST"
239 239 #endif
240 240 (void) textdomain(TEXT_DOMAIN);
241 241
242 242 myname = strrchr(argv[0], '/');
243 243 myname = myname ? myname + 1 : argv[0];
244 244 (void) snprintf(typename, sizeof (typename), "%s %s",
245 245 MNTTYPE_NFS, myname);
246 246 argv[0] = typename;
247 247
248 248 mnt.mnt_mntopts = optbuf;
249 249 (void) strcpy(optbuf, "rw");
250 250
251 251 /*
252 252 * Set options
253 253 */
254 254 while ((c = getopt(argc, argv, "ro:mOq")) != EOF) {
255 255 switch (c) {
256 256 case 'r':
257 257 ro++;
258 258 break;
259 259 case 'o':
260 260 if (strlen(optarg) >= MAX_MNTOPT_STR) {
261 261 pr_err(gettext("option string too long"));
262 262 return (RET_ERR);
263 263 }
264 264 (void) strcpy(mnt.mnt_mntopts, optarg);
265 265 #ifdef LATER /* XXX */
266 266 if (strstr(optarg, MNTOPT_REMOUNT)) {
267 267 /*
268 268 * If remount is specified, only rw is allowed.
269 269 */
270 270 if ((strcmp(optarg, MNTOPT_REMOUNT) != 0) &&
271 271 (strcmp(optarg, "remount,rw") != 0) &&
272 272 (strcmp(optarg, "rw,remount") != 0)) {
273 273 pr_err(gettext("Invalid options\n"));
274 274 exit(RET_ERR);
275 275 }
276 276 }
277 277 #endif /* LATER */ /* XXX */
278 278 break;
279 279 case 'm':
280 280 mflg++;
281 281 break;
282 282 case 'O':
283 283 Oflg++;
284 284 break;
285 285 case 'q':
286 286 qflg++;
287 287 break;
288 288 default:
289 289 usage();
290 290 exit(RET_ERR);
291 291 }
292 292 }
293 293 if (argc - optind != 2) {
294 294 usage();
295 295 exit(RET_ERR);
296 296 }
297 297
298 298 mnt.mnt_special = argv[optind];
299 299 mnt.mnt_mountp = argv[optind+1];
300 300
301 301 if (!priv_ineffect(PRIV_SYS_MOUNT) ||
302 302 !priv_ineffect(PRIV_NET_PRIVADDR)) {
303 303 pr_err(gettext("insufficient privileges\n"));
304 304 exit(RET_ERR);
305 305 }
306 306
307 307 /*
308 308 * On a labeled system, allow read-down nfs mounts if privileged
309 309 * (PRIV_NET_MAC_AWARE) to do so. Otherwise, ignore the error
310 310 * and "mount equal label only" behavior will result.
311 311 */
312 312 if (is_system_labeled())
↓ open down ↓ |
174 lines elided |
↑ open up ↑ |
313 313 (void) setpflags(NET_MAC_AWARE, 1);
314 314
315 315 /*
316 316 * Read the defaults file to see if the min/max versions have
317 317 * been set and therefore would override the encoded defaults.
318 318 * Then check to make sure that if they were set that the
319 319 * values are reasonable.
320 320 */
321 321 read_default();
322 322 if (vers_min_default > vers_max_default ||
323 - vers_min_default < NFS_VERSMIN ||
324 - vers_max_default > NFS_VERSMAX) {
323 + vers_min_default < NFS_VERSMIN ||
324 + vers_max_default > NFS_VERSMAX) {
325 325 pr_err("%s %s\n%s %s\n",
326 - gettext("Incorrect configuration of client\'s"),
327 - NFSADMIN,
328 - gettext("NFS_CLIENT_VERSMIN or NFS_CLIENT_VERSMAX"),
329 - gettext("is either out of range or overlaps."));
326 + gettext("Incorrect configuration of client\'s"),
327 + NFSADMIN,
328 + gettext("NFS_CLIENT_VERSMIN or NFS_CLIENT_VERSMAX"),
329 + gettext("is either out of range or overlaps."));
330 330 }
331 331
332 332 SET_ERR_RET(&retry_error, ERR_PROTO_NONE, 0);
333 333 r = mount_nfs(&mnt, ro, &retry_error);
334 334 if (r == RET_RETRY && retries) {
335 335 /*
336 336 * Check the error code from the last mount attempt if it was
337 337 * an RPC error, then retry as is. Otherwise we retry with the
338 338 * nfsretry_vers set. It is set by decrementing nfsvers_to_use.
339 339 * If we are retrying with nfsretry_vers then we don't print any
340 340 * retry messages, since we are not retrying due to an RPC
341 341 * error.
342 342 */
343 343 if (retry_error.error_type) {
344 344 if (retry_error.error_type != ERR_RPCERROR) {
345 345 nfsretry_vers = nfsvers_to_use =
346 346 nfsvers_to_use - 1;
347 347 if (nfsretry_vers < NFS_VERSMIN)
348 348 return (r);
349 349 }
350 350 }
351 351
352 352 r = retry(&mnt, ro);
353 353 }
354 354 /*
355 355 * exit(r);
356 356 */
357 357 return (r);
358 358 }
359 359
360 360 static void
361 361 pr_err(const char *fmt, ...)
362 362 {
363 363 va_list ap;
364 364
365 365 va_start(ap, fmt);
366 366 if (backgrounded != 0) {
367 367 (void) vsyslog(LOG_ERR, fmt, ap);
368 368 } else {
369 369 (void) fprintf(stderr, "%s: ", typename);
370 370 (void) vfprintf(stderr, fmt, ap);
371 371 (void) fflush(stderr);
372 372 }
373 373 va_end(ap);
374 374 }
375 375
376 376 static void
377 377 usage()
378 378 {
379 379 (void) fprintf(stderr,
380 380 gettext("Usage: nfs mount [-r] [-o opts] [server:]path dir\n"));
381 381 exit(RET_ERR);
382 382 }
383 383
384 384 static int
385 385 mount_nfs(struct mnttab *mntp, int ro, err_ret_t *retry_error)
386 386 {
387 387 struct nfs_args *args = NULL, *argp = NULL, *prev_argp = NULL;
388 388 struct netconfig *nconf = NULL;
389 389 struct replica *list = NULL;
390 390 int mntflags = 0;
391 391 int i, r, n;
392 392 int oldvers = 0, vers = 0;
393 393 int last_error = RET_OK;
394 394 int replicated = 0;
395 395 char *p;
396 396 bool_t url;
397 397 bool_t use_pubfh;
398 398 char *special = NULL;
399 399 char *oldpath = NULL;
400 400 char *newpath = NULL;
401 401 char *service;
402 402 pid_t pi;
403 403 struct flock f;
404 404 char *saveopts = NULL;
405 405 char **sl = NULL;
406 406
407 407 mntp->mnt_fstype = MNTTYPE_NFS;
408 408
409 409 if (ro) {
410 410 mntflags |= MS_RDONLY;
411 411 /* convert "rw"->"ro" */
412 412 if (p = strstr(mntp->mnt_mntopts, "rw")) {
413 413 if (*(p+2) == ',' || *(p+2) == '\0')
414 414 *(p+1) = 'o';
415 415 }
416 416 }
417 417
418 418 if (Oflg)
419 419 mntflags |= MS_OVERLAY;
420 420
421 421 list = parse_replica(mntp->mnt_special, &n);
422 422 if (list == NULL) {
423 423 if (n < 0)
424 424 pr_err(gettext("nfs file system; use [host:]path\n"));
425 425 else
426 426 pr_err(gettext("no memory\n"));
427 427 return (RET_ERR);
428 428 }
429 429
430 430 replicated = (n > 1);
431 431
432 432 /*
433 433 * There are some free() calls at the bottom of this loop, so be
434 434 * careful about adding continue statements.
435 435 */
436 436 for (i = 0; i < n; i++) {
437 437 char *path;
438 438 char *host;
439 439 ushort_t port;
440 440
441 441 argp = (struct nfs_args *)malloc(sizeof (*argp));
442 442 if (argp == NULL) {
443 443 pr_err(gettext("no memory\n"));
444 444 last_error = RET_ERR;
445 445 goto out;
446 446 }
447 447 memset(argp, 0, sizeof (*argp));
448 448
449 449 memset(&nfs_sec, 0, sizeof (nfs_sec));
450 450 sec_opt = 0;
451 451 use_pubfh = FALSE;
452 452 url = FALSE;
453 453 port = 0;
454 454 snego_done = FALSE;
455 455
456 456 /*
457 457 * Looking for resources of the form
458 458 * nfs://server_host[:port_number]/path_name
459 459 */
460 460 if (strcmp(list[i].host, "nfs") == 0 && strncmp(list[i].path,
461 461 "//", 2) == 0) {
462 462 char *sport, *cb;
463 463 url = TRUE;
464 464 oldpath = strdup(list[i].path);
465 465 if (oldpath == NULL) {
466 466 pr_err(gettext("memory allocation failure\n"));
467 467 last_error = RET_ERR;
468 468 goto out;
469 469 }
470 470 host = list[i].path+2;
471 471 path = strchr(host, '/');
472 472
473 473 if (path == NULL) {
474 474 pr_err(gettext(
↓ open down ↓ |
135 lines elided |
↑ open up ↑ |
475 475 "illegal nfs url syntax\n"));
476 476 last_error = RET_ERR;
477 477 goto out;
478 478 }
479 479
480 480 *path = '\0';
481 481 if (*host == '[') {
482 482 cb = strchr(host, ']');
483 483 if (cb == NULL) {
484 484 pr_err(gettext(
485 - "illegal nfs url syntax\n"));
485 + "illegal nfs url syntax\n"));
486 486 last_error = RET_ERR;
487 487 goto out;
488 488 } else {
489 489 *cb = '\0';
490 490 host++;
491 491 cb++;
492 492 if (*cb == ':')
493 493 port = htons((ushort_t)
494 - atoi(cb+1));
494 + atoi(cb+1));
495 495 }
496 496 } else {
497 497 sport = strchr(host, ':');
498 498
499 499 if (sport != NULL && sport < path) {
500 500 *sport = '\0';
501 501 port = htons((ushort_t)atoi(sport+1));
502 502 }
503 503 }
504 504
505 505 path++;
506 506 if (*path == '\0')
507 507 path = ".";
508 508
509 509 } else {
510 510 host = list[i].host;
511 511 path = list[i].path;
512 512 }
513 513
514 514 if (r = set_args(&mntflags, argp, host, mntp)) {
515 515 last_error = r;
516 516 goto out;
517 517 }
518 518
519 519 if (public_opt == TRUE)
520 520 use_pubfh = TRUE;
521 521
522 522 if (port == 0) {
523 523 port = nfs_port;
524 524 } else if (nfs_port != 0 && nfs_port != port) {
525 525 pr_err(gettext(
526 526 "port (%u) in nfs URL not the same"
↓ open down ↓ |
22 lines elided |
↑ open up ↑ |
527 527 " as port (%u) in port option\n"),
528 528 (unsigned int)ntohs(port),
529 529 (unsigned int)ntohs(nfs_port));
530 530 last_error = RET_ERR;
531 531 goto out;
532 532 }
533 533
534 534
535 535 if (replicated && !(mntflags & MS_RDONLY)) {
536 536 pr_err(gettext(
537 - "replicated mounts must be read-only\n"));
537 + "replicated mounts must be read-only\n"));
538 538 last_error = RET_ERR;
539 539 goto out;
540 540 }
541 541
542 542 if (replicated && (argp->flags & NFSMNT_SOFT)) {
543 543 pr_err(gettext(
544 - "replicated mounts must not be soft\n"));
544 + "replicated mounts must not be soft\n"));
545 545 last_error = RET_ERR;
546 546 goto out;
547 547 }
548 548
549 549 oldvers = vers;
550 550 nconf = NULL;
551 551
552 552 r = RET_ERR;
553 553
554 554 /*
555 555 * If -o public was specified, and/or a URL was specified,
556 556 * then try the public file handle method.
557 557 */
558 558 if ((use_pubfh == TRUE) || (url == TRUE)) {
559 559 r = get_fh_via_pub(argp, host, path, url, use_pubfh,
560 - &vers, &nconf, port);
560 + &vers, &nconf, port);
561 561
562 562 if (r != RET_OK) {
563 563 /*
564 564 * If -o public was specified, then return the
565 565 * error now.
566 566 */
567 567 if (use_pubfh == TRUE) {
568 568 last_error = r;
569 569 goto out;
570 570 }
571 571 } else
572 572 use_pubfh = TRUE;
573 573 argp->flags |= NFSMNT_PUBLIC;
574 574 }
575 575
576 576 if ((r != RET_OK) || (vers == NFS_V4)) {
577 577 bool_t loud_on_mnt_err;
578 578
579 579 /*
580 580 * This can happen if -o public is not specified,
581 581 * special is a URL, and server doesn't support
582 582 * public file handle.
583 583 */
584 584 if (url) {
585 585 URLparse(path);
586 586 }
587 587
588 588 /*
589 589 * If the path portion of the URL didn't have
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
590 590 * a leading / then there is good possibility
591 591 * that a mount without a leading slash will
592 592 * fail.
593 593 */
594 594 if (url == TRUE && *path != '/')
595 595 loud_on_mnt_err = FALSE;
596 596 else
597 597 loud_on_mnt_err = TRUE;
598 598
599 599 r = get_fh(argp, host, path, &vers,
600 - loud_on_mnt_err, &nconf, port);
600 + loud_on_mnt_err, &nconf, port);
601 601
602 602 if (r != RET_OK) {
603 603
604 604 /*
605 605 * If there was no leading / and the path was
606 606 * derived from a URL, then try again
607 607 * with a leading /.
608 608 */
609 609 if ((r == RET_MNTERR) &&
610 610 (loud_on_mnt_err == FALSE)) {
611 611
612 612 newpath = malloc(strlen(path)+2);
613 613
614 614 if (newpath == NULL) {
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
615 615 pr_err(gettext("memory "
616 616 "allocation failure\n"));
617 617 last_error = RET_ERR;
618 618 goto out;
619 619 }
620 620
621 621 strcpy(newpath, "/");
622 622 strcat(newpath, path);
623 623
624 624 r = get_fh(argp, host, newpath, &vers,
625 - TRUE, &nconf, port);
625 + TRUE, &nconf, port);
626 626
627 627 if (r == RET_OK)
628 628 path = newpath;
629 629 }
630 630
631 631 /*
632 632 * map exit code back to RET_ERR.
633 633 */
634 634 if (r == RET_MNTERR)
635 635 r = RET_ERR;
636 636
637 637 if (r != RET_OK) {
638 638
639 639 if (replicated) {
640 640 if (argp->fh)
641 641 free(argp->fh);
642 642 if (argp->pathconf)
643 643 free(argp->pathconf);
644 644 free(argp);
645 645 goto cont;
646 646 }
647 647
648 648 last_error = r;
649 649 goto out;
650 650 }
651 651 }
652 652 }
653 653
654 654 if (oldvers && vers != oldvers) {
655 655 pr_err(
656 656 gettext("replicas must have the same version\n"));
657 657 last_error = RET_ERR;
658 658 goto out;
659 659 }
660 660
661 661 /*
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
662 662 * decide whether to use remote host's
663 663 * lockd or do local locking
664 664 */
665 665 if (!(argp->flags & NFSMNT_LLOCK) && vers == NFS_VERSION &&
666 666 remote_lock(host, argp->fh)) {
667 667 (void) fprintf(stderr, gettext(
668 668 "WARNING: No network locking on %s:%s:"),
669 669 host, path);
670 670 (void) fprintf(stderr, gettext(
671 671 " contact admin to install server change\n"));
672 - argp->flags |= NFSMNT_LLOCK;
672 + argp->flags |= NFSMNT_LLOCK;
673 673 }
674 674
675 675 if (self_check(host))
676 676 argp->flags |= NFSMNT_LOOPBACK;
677 677
678 678 if (use_pubfh == FALSE) {
679 679 /*
680 680 * Call to get_fh() above may have obtained the
681 681 * netconfig info and NULL proc'd the server.
682 682 * This would be the case with v4
683 683 */
684 684 if (!(argp->flags & NFSMNT_KNCONF)) {
685 685 nconf = NULL;
686 686 if (r = getaddr_nfs(argp, host, &nconf,
687 - FALSE, path, port, retry_error,
688 - TRUE)) {
689 - last_error = r;
690 - goto out;
687 + FALSE, path, port, retry_error,
688 + TRUE)) {
689 + last_error = r;
690 + goto out;
691 691 }
692 692 }
693 693 }
694 694
695 695 if (make_secure(argp, host, nconf, use_pubfh, vers) < 0) {
696 696 last_error = RET_ERR;
697 697 goto out;
698 698 }
699 699
700 700 if ((url == TRUE) && (use_pubfh == FALSE)) {
701 701 /*
702 702 * Convert the special from
703 703 * nfs://host/path
704 704 * to
705 705 * host:path
706 706 */
707 707 if (convert_special(&special, host, oldpath, path,
708 708 mntp->mnt_special) == -1) {
709 709 (void) fprintf(stderr, gettext(
710 710 "could not convert URL nfs:%s to %s:%s\n"),
711 711 oldpath, host, path);
712 712 last_error = RET_ERR;
713 713 goto out;
714 714 } else {
715 715 mntp->mnt_special = special;
716 716 }
717 717 }
718 718
719 719 if (prev_argp == NULL)
720 720 args = argp;
721 721 else
722 722 prev_argp->nfs_ext_u.nfs_extB.next = argp;
723 723 prev_argp = argp;
724 724
725 725 cont:
726 726 if (oldpath != NULL) {
727 727 free(oldpath);
728 728 oldpath = NULL;
729 729 }
730 730
731 731 if (newpath != NULL) {
732 732 free(newpath);
733 733 newpath = NULL;
734 734 }
735 735 }
736 736
737 737 argp = NULL;
738 738
739 739 if (args == NULL) {
740 740 last_error = RET_RETRY;
741 741 goto out;
742 742 }
743 743
744 744 /* Determine which services are appropriate for the NFS version */
745 745 if (strcmp(fstype, MNTTYPE_NFS4) == 0)
746 746 sl = service_list_v4;
747 747 else
748 748 sl = service_list;
749 749
750 750 /*
751 751 * enable services as needed.
752 752 */
753 753 _check_services(sl);
↓ open down ↓ |
53 lines elided |
↑ open up ↑ |
754 754
755 755 mntflags |= MS_DATA | MS_OPTIONSTR;
756 756
757 757 if (mflg)
758 758 mntflags |= MS_NOMNTTAB;
759 759
760 760 if (!qflg)
761 761 saveopts = strdup(mntp->mnt_mntopts);
762 762
763 763 if (mount(mntp->mnt_special, mntp->mnt_mountp, mntflags, fstype, args,
764 - sizeof (*args), mntp->mnt_mntopts, MAX_MNTOPT_STR) < 0) {
764 + sizeof (*args), mntp->mnt_mntopts, MAX_MNTOPT_STR) < 0) {
765 765 if (errno != ENOENT) {
766 766 pr_err(gettext("mount: %s: %s\n"),
767 - mntp->mnt_mountp, strerror(errno));
767 + mntp->mnt_mountp, strerror(errno));
768 768 } else {
769 769 struct stat sb;
770 770 if (stat(mntp->mnt_mountp, &sb) < 0 && errno == ENOENT)
771 771 pr_err(gettext("mount: %s: %s\n"),
772 - mntp->mnt_mountp, strerror(ENOENT));
772 + mntp->mnt_mountp, strerror(ENOENT));
773 773 else
774 774 pr_err("%s: %s\n", mntp->mnt_special,
775 - strerror(ENOENT));
775 + strerror(ENOENT));
776 776 }
777 777
778 778 last_error = RET_ERR;
779 779 goto out;
780 780 }
781 781
782 782 if (!qflg && saveopts != NULL) {
783 783 cmp_requested_to_actual_options(saveopts, mntp->mnt_mntopts,
784 784 mntp->mnt_special, mntp->mnt_mountp);
785 785 }
786 786
787 787 out:
788 788 if (saveopts != NULL)
789 789 free(saveopts);
790 790 if (special != NULL)
791 791 free(special);
792 792 if (oldpath != NULL)
793 793 free(oldpath);
794 794 if (newpath != NULL)
795 795 free(newpath);
796 796
797 797 free_replica(list, n);
798 798
799 799 if (argp != NULL) {
800 800 /*
801 801 * If we had a new entry which was not added to the
802 802 * list yet, then add it now that it can be freed.
803 803 */
804 804 if (prev_argp == NULL)
805 805 args = argp;
806 806 else
807 807 prev_argp->nfs_ext_u.nfs_extB.next = argp;
808 808 }
809 809 argp = args;
810 810 while (argp != NULL) {
811 811 if (argp->fh)
812 812 free(argp->fh);
813 813 if (argp->pathconf)
814 814 free(argp->pathconf);
815 815 if (argp->knconf)
816 816 free(argp->knconf);
817 817 if (argp->addr) {
818 818 free(argp->addr->buf);
819 819 free(argp->addr);
820 820 }
821 821 nfs_free_secdata(argp->nfs_ext_u.nfs_extB.secdata);
822 822 if (argp->syncaddr) {
823 823 free(argp->syncaddr->buf);
824 824 free(argp->syncaddr);
825 825 }
826 826 if (argp->netname)
827 827 free(argp->netname);
828 828 prev_argp = argp;
829 829 argp = argp->nfs_ext_u.nfs_extB.next;
830 830 free(prev_argp);
831 831 }
832 832
833 833 return (last_error);
834 834 }
835 835
836 836 /*
837 837 * These options are duplicated in uts/common/fs/nfs/nfs_dlinet.c
838 838 * Changes must be made to both lists.
839 839 */
840 840 static char *optlist[] = {
841 841 #define OPT_RO 0
842 842 MNTOPT_RO,
843 843 #define OPT_RW 1
844 844 MNTOPT_RW,
845 845 #define OPT_QUOTA 2
846 846 MNTOPT_QUOTA,
847 847 #define OPT_NOQUOTA 3
848 848 MNTOPT_NOQUOTA,
849 849 #define OPT_SOFT 4
850 850 MNTOPT_SOFT,
851 851 #define OPT_HARD 5
852 852 MNTOPT_HARD,
853 853 #define OPT_SUID 6
854 854 MNTOPT_SUID,
855 855 #define OPT_NOSUID 7
856 856 MNTOPT_NOSUID,
857 857 #define OPT_GRPID 8
858 858 MNTOPT_GRPID,
859 859 #define OPT_REMOUNT 9
860 860 MNTOPT_REMOUNT,
861 861 #define OPT_NOSUB 10
862 862 MNTOPT_NOSUB,
863 863 #define OPT_INTR 11
864 864 MNTOPT_INTR,
865 865 #define OPT_NOINTR 12
866 866 MNTOPT_NOINTR,
867 867 #define OPT_PORT 13
868 868 MNTOPT_PORT,
869 869 #define OPT_SECURE 14
870 870 MNTOPT_SECURE,
871 871 #define OPT_RSIZE 15
872 872 MNTOPT_RSIZE,
873 873 #define OPT_WSIZE 16
874 874 MNTOPT_WSIZE,
875 875 #define OPT_TIMEO 17
876 876 MNTOPT_TIMEO,
877 877 #define OPT_RETRANS 18
878 878 MNTOPT_RETRANS,
879 879 #define OPT_ACTIMEO 19
880 880 MNTOPT_ACTIMEO,
881 881 #define OPT_ACREGMIN 20
882 882 MNTOPT_ACREGMIN,
883 883 #define OPT_ACREGMAX 21
884 884 MNTOPT_ACREGMAX,
885 885 #define OPT_ACDIRMIN 22
886 886 MNTOPT_ACDIRMIN,
887 887 #define OPT_ACDIRMAX 23
888 888 MNTOPT_ACDIRMAX,
889 889 #define OPT_BG 24
890 890 MNTOPT_BG,
891 891 #define OPT_FG 25
892 892 MNTOPT_FG,
893 893 #define OPT_RETRY 26
894 894 MNTOPT_RETRY,
895 895 #define OPT_NOAC 27
896 896 MNTOPT_NOAC,
897 897 #define OPT_NOCTO 28
898 898 MNTOPT_NOCTO,
899 899 #define OPT_LLOCK 29
900 900 MNTOPT_LLOCK,
901 901 #define OPT_POSIX 30
902 902 MNTOPT_POSIX,
903 903 #define OPT_VERS 31
904 904 MNTOPT_VERS,
905 905 #define OPT_PROTO 32
906 906 MNTOPT_PROTO,
907 907 #define OPT_SEMISOFT 33
908 908 MNTOPT_SEMISOFT,
909 909 #define OPT_NOPRINT 34
910 910 MNTOPT_NOPRINT,
911 911 #define OPT_SEC 35
912 912 MNTOPT_SEC,
913 913 #define OPT_LARGEFILES 36
914 914 MNTOPT_LARGEFILES,
915 915 #define OPT_NOLARGEFILES 37
916 916 MNTOPT_NOLARGEFILES,
917 917 #define OPT_PUBLIC 38
918 918 MNTOPT_PUBLIC,
919 919 #define OPT_DIRECTIO 39
920 920 MNTOPT_FORCEDIRECTIO,
921 921 #define OPT_NODIRECTIO 40
922 922 MNTOPT_NOFORCEDIRECTIO,
923 923 #define OPT_XATTR 41
924 924 MNTOPT_XATTR,
925 925 #define OPT_NOXATTR 42
926 926 MNTOPT_NOXATTR,
927 927 #define OPT_DEVICES 43
928 928 MNTOPT_DEVICES,
929 929 #define OPT_NODEVICES 44
930 930 MNTOPT_NODEVICES,
931 931 #define OPT_SETUID 45
932 932 MNTOPT_SETUID,
933 933 #define OPT_NOSETUID 46
934 934 MNTOPT_NOSETUID,
935 935 #define OPT_EXEC 47
936 936 MNTOPT_EXEC,
937 937 #define OPT_NOEXEC 48
938 938 MNTOPT_NOEXEC,
939 939 NULL
940 940 };
941 941
942 942 #define bad(val) (val == NULL || !isdigit(*val))
943 943
944 944 static int
945 945 set_args(int *mntflags, struct nfs_args *args, char *fshost, struct mnttab *mnt)
946 946 {
947 947 char *saveopt, *optstr, *opts, *newopts, *val;
948 948 int largefiles = 0;
949 949 int invalid = 0;
950 950 int attrpref = 0;
951 951 int optlen;
952 952
953 953 args->flags = NFSMNT_INT; /* default is "intr" */
954 954 args->flags |= NFSMNT_HOSTNAME;
955 955 args->flags |= NFSMNT_NEWARGS; /* using extented nfs_args structure */
956 956 args->hostname = fshost;
957 957
958 958 optstr = opts = strdup(mnt->mnt_mntopts);
959 959 /* sizeof (MNTOPT_XXX) includes one extra byte we may need for "," */
960 960 optlen = strlen(mnt->mnt_mntopts) + sizeof (MNTOPT_XATTR) + 1;
961 961 if (optlen > MAX_MNTOPT_STR) {
962 962 pr_err(gettext("option string too long"));
963 963 return (RET_ERR);
964 964 }
965 965 newopts = malloc(optlen);
966 966 if (opts == NULL || newopts == NULL) {
967 967 pr_err(gettext("no memory"));
968 968 if (opts)
969 969 free(opts);
970 970 if (newopts)
971 971 free(newopts);
972 972 return (RET_ERR);
973 973 }
974 974 newopts[0] = '\0';
975 975
976 976 while (*opts) {
977 977 invalid = 0;
978 978 saveopt = opts;
979 979 switch (getsubopt(&opts, optlist, &val)) {
980 980 case OPT_RO:
981 981 *mntflags |= MS_RDONLY;
982 982 break;
983 983 case OPT_RW:
984 984 *mntflags &= ~(MS_RDONLY);
985 985 break;
986 986 case OPT_QUOTA:
987 987 case OPT_NOQUOTA:
988 988 break;
989 989 case OPT_SOFT:
990 990 args->flags |= NFSMNT_SOFT;
991 991 args->flags &= ~(NFSMNT_SEMISOFT);
992 992 break;
993 993 case OPT_SEMISOFT:
994 994 args->flags |= NFSMNT_SOFT;
995 995 args->flags |= NFSMNT_SEMISOFT;
996 996 break;
997 997 case OPT_HARD:
998 998 args->flags &= ~(NFSMNT_SOFT);
999 999 args->flags &= ~(NFSMNT_SEMISOFT);
1000 1000 break;
1001 1001 case OPT_SUID:
1002 1002 *mntflags &= ~(MS_NOSUID);
1003 1003 break;
1004 1004 case OPT_NOSUID:
1005 1005 *mntflags |= MS_NOSUID;
1006 1006 break;
1007 1007 case OPT_GRPID:
1008 1008 args->flags |= NFSMNT_GRPID;
1009 1009 break;
1010 1010 case OPT_REMOUNT:
1011 1011 *mntflags |= MS_REMOUNT;
1012 1012 break;
1013 1013 case OPT_INTR:
1014 1014 args->flags |= NFSMNT_INT;
1015 1015 break;
1016 1016 case OPT_NOINTR:
1017 1017 args->flags &= ~(NFSMNT_INT);
1018 1018 break;
1019 1019 case OPT_NOAC:
↓ open down ↓ |
234 lines elided |
↑ open up ↑ |
1020 1020 args->flags |= NFSMNT_NOAC;
1021 1021 break;
1022 1022 case OPT_PORT:
1023 1023 if (bad(val))
1024 1024 goto badopt;
1025 1025 nfs_port = htons((ushort_t)atoi(val));
1026 1026 break;
1027 1027
1028 1028 case OPT_SECURE:
1029 1029 if (nfs_getseconfig_byname("dh", &nfs_sec)) {
1030 - pr_err(gettext("can not get \"dh\" from %s\n"),
1031 - NFSSEC_CONF);
1032 - goto badopt;
1030 + pr_err(gettext("can not get \"dh\" from %s\n"),
1031 + NFSSEC_CONF);
1032 + goto badopt;
1033 1033 }
1034 1034 sec_opt++;
1035 1035 break;
1036 1036
1037 1037 case OPT_NOCTO:
1038 1038 args->flags |= NFSMNT_NOCTO;
1039 1039 break;
1040 1040
1041 1041 case OPT_RSIZE:
1042 1042 args->flags |= NFSMNT_RSIZE;
1043 1043 if (bad(val))
1044 1044 goto badopt;
1045 1045 args->rsize = atoi(val);
1046 1046 break;
1047 1047 case OPT_WSIZE:
1048 1048 args->flags |= NFSMNT_WSIZE;
1049 1049 if (bad(val))
1050 1050 goto badopt;
1051 1051 args->wsize = atoi(val);
1052 1052 break;
1053 1053 case OPT_TIMEO:
1054 1054 args->flags |= NFSMNT_TIMEO;
1055 1055 if (bad(val))
1056 1056 goto badopt;
1057 1057 args->timeo = atoi(val);
1058 1058 break;
1059 1059 case OPT_RETRANS:
1060 1060 args->flags |= NFSMNT_RETRANS;
1061 1061 if (bad(val))
1062 1062 goto badopt;
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
1063 1063 args->retrans = atoi(val);
1064 1064 break;
1065 1065 case OPT_ACTIMEO:
1066 1066 args->flags |= NFSMNT_ACDIRMAX;
1067 1067 args->flags |= NFSMNT_ACREGMAX;
1068 1068 args->flags |= NFSMNT_ACDIRMIN;
1069 1069 args->flags |= NFSMNT_ACREGMIN;
1070 1070 if (bad(val))
1071 1071 goto badopt;
1072 1072 args->acdirmin = args->acregmin = args->acdirmax
1073 - = args->acregmax = atoi(val);
1073 + = args->acregmax = atoi(val);
1074 1074 break;
1075 1075 case OPT_ACREGMIN:
1076 1076 args->flags |= NFSMNT_ACREGMIN;
1077 1077 if (bad(val))
1078 1078 goto badopt;
1079 1079 args->acregmin = atoi(val);
1080 1080 break;
1081 1081 case OPT_ACREGMAX:
1082 1082 args->flags |= NFSMNT_ACREGMAX;
1083 1083 if (bad(val))
1084 1084 goto badopt;
1085 1085 args->acregmax = atoi(val);
1086 1086 break;
1087 1087 case OPT_ACDIRMIN:
1088 1088 args->flags |= NFSMNT_ACDIRMIN;
1089 1089 if (bad(val))
1090 1090 goto badopt;
1091 1091 args->acdirmin = atoi(val);
1092 1092 break;
1093 1093 case OPT_ACDIRMAX:
1094 1094 args->flags |= NFSMNT_ACDIRMAX;
1095 1095 if (bad(val))
1096 1096 goto badopt;
1097 1097 args->acdirmax = atoi(val);
1098 1098 break;
1099 1099 case OPT_BG:
1100 1100 bg++;
1101 1101 break;
1102 1102 case OPT_FG:
1103 1103 bg = 0;
1104 1104 break;
1105 1105 case OPT_RETRY:
1106 1106 if (bad(val))
1107 1107 goto badopt;
1108 1108 retries = atoi(val);
1109 1109 break;
1110 1110 case OPT_LLOCK:
1111 1111 args->flags |= NFSMNT_LLOCK;
1112 1112 break;
1113 1113 case OPT_POSIX:
1114 1114 posix = 1;
1115 1115 break;
1116 1116 case OPT_VERS:
1117 1117 if (bad(val))
1118 1118 goto badopt;
1119 1119 nfsvers = (rpcvers_t)atoi(val);
1120 1120 break;
1121 1121 case OPT_PROTO:
1122 1122 if (val == NULL)
1123 1123 goto badopt;
1124 1124
1125 1125 nfs_proto = (char *)malloc(strlen(val)+1);
1126 1126 if (!nfs_proto) {
1127 1127 pr_err(gettext("no memory"));
1128 1128 return (RET_ERR);
1129 1129 }
1130 1130
1131 1131 (void) strncpy(nfs_proto, val, strlen(val)+1);
1132 1132 break;
1133 1133 case OPT_NOPRINT:
1134 1134 args->flags |= NFSMNT_NOPRINT;
1135 1135 break;
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
1136 1136 case OPT_LARGEFILES:
1137 1137 largefiles = 1;
1138 1138 break;
1139 1139 case OPT_NOLARGEFILES:
1140 1140 pr_err(gettext("NFS can't support \"nolargefiles\"\n"));
1141 1141 free(optstr);
1142 1142 return (RET_ERR);
1143 1143
1144 1144 case OPT_SEC:
1145 1145 if (nfs_getseconfig_byname(val, &nfs_sec)) {
1146 - pr_err(gettext("can not get \"%s\" from %s\n"),
1147 - val, NFSSEC_CONF);
1148 - return (RET_ERR);
1146 + pr_err(gettext("can not get \"%s\" from %s\n"),
1147 + val, NFSSEC_CONF);
1148 + return (RET_ERR);
1149 1149 }
1150 1150 sec_opt++;
1151 1151 break;
1152 1152
1153 1153 case OPT_PUBLIC:
1154 1154 public_opt = TRUE;
1155 1155 break;
1156 1156
1157 1157 case OPT_DIRECTIO:
1158 1158 args->flags |= NFSMNT_DIRECTIO;
1159 1159 break;
1160 1160
1161 1161 case OPT_NODIRECTIO:
1162 1162 args->flags &= ~(NFSMNT_DIRECTIO);
1163 1163 break;
1164 1164
1165 1165 case OPT_XATTR:
1166 1166 case OPT_NOXATTR:
1167 1167 /*
1168 1168 * VFS options; just need to get them into the
1169 1169 * new mount option string and note we've seen them
1170 1170 */
1171 1171 attrpref = 1;
1172 1172 break;
1173 1173 default:
1174 1174 /*
1175 1175 * Note that this could be a valid OPT_* option so
1176 1176 * we can't use "val" but need to use "saveopt".
1177 1177 */
1178 1178 if (fsisstdopt(saveopt))
1179 1179 break;
1180 1180 invalid = 1;
1181 1181 if (!qflg)
1182 1182 (void) fprintf(stderr, gettext(
1183 1183 "mount: %s on %s - WARNING unknown option"
1184 1184 " \"%s\"\n"), mnt->mnt_special,
1185 1185 mnt->mnt_mountp, saveopt);
1186 1186 break;
1187 1187 }
1188 1188 if (!invalid) {
1189 1189 if (newopts[0])
1190 1190 strcat(newopts, ",");
1191 1191 strcat(newopts, saveopt);
1192 1192 }
1193 1193 }
1194 1194 /* Default is to turn extended attrs on */
1195 1195 if (!attrpref) {
1196 1196 if (newopts[0])
1197 1197 strcat(newopts, ",");
1198 1198 strcat(newopts, MNTOPT_XATTR);
1199 1199 }
1200 1200 strcpy(mnt->mnt_mntopts, newopts);
1201 1201 free(newopts);
1202 1202 free(optstr);
1203 1203
1204 1204 /* ensure that only one secure mode is requested */
1205 1205 if (sec_opt > 1) {
1206 1206 pr_err(gettext("Security options conflict\n"));
1207 1207 return (RET_ERR);
1208 1208 }
1209 1209
1210 1210 /* ensure that the user isn't trying to get large files over V2 */
1211 1211 if (nfsvers == NFS_VERSION && largefiles) {
1212 1212 pr_err(gettext("NFS V2 can't support \"largefiles\"\n"));
1213 1213 return (RET_ERR);
1214 1214 }
1215 1215
1216 1216 if (nfsvers == NFS_V4 &&
1217 1217 nfs_proto != NULL &&
1218 1218 strncasecmp(nfs_proto, NC_UDP, strlen(NC_UDP)) == 0) {
1219 1219 pr_err(gettext("NFS V4 does not support %s\n"), nfs_proto);
1220 1220 return (RET_ERR);
1221 1221 }
1222 1222
1223 1223 return (RET_OK);
1224 1224
1225 1225 badopt:
1226 1226 pr_err(gettext("invalid option: \"%s\"\n"), saveopt);
1227 1227 free(optstr);
1228 1228 return (RET_ERR);
1229 1229 }
1230 1230
1231 1231 static int
1232 1232 make_secure(struct nfs_args *args, char *hostname, struct netconfig *nconf,
1233 1233 bool_t use_pubfh, rpcvers_t vers)
1234 1234 {
1235 1235 sec_data_t *secdata;
1236 1236 int flags;
1237 1237 struct netbuf *syncaddr = NULL;
1238 1238 struct nd_addrlist *retaddrs = NULL;
1239 1239 char netname[MAXNETNAMELEN+1];
1240 1240
1241 1241 /*
1242 1242 * check to see if any secure mode is requested.
1243 1243 * if not, use default security mode.
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
1244 1244 */
1245 1245 if (!snego_done && !sec_opt) {
1246 1246 /*
1247 1247 * Get default security mode.
1248 1248 * AUTH_UNIX has been the default choice for a long time.
1249 1249 * The better NFS security service becomes, the better chance
1250 1250 * we will set stronger security service as the default NFS
1251 1251 * security mode.
1252 1252 *
1253 1253 */
1254 - if (nfs_getseconfig_default(&nfs_sec)) {
1255 - pr_err(gettext("error getting default security entry\n"));
1256 - return (-1);
1257 - }
1258 - args->flags |= NFSMNT_SECDEFAULT;
1254 + if (nfs_getseconfig_default(&nfs_sec)) {
1255 + pr_err(gettext("error getting default"
1256 + " security entry\n"));
1257 + return (-1);
1258 + }
1259 + args->flags |= NFSMNT_SECDEFAULT;
1259 1260 }
1260 1261
1261 1262 /*
1262 1263 * Get the network address for the time service on the server.
1263 1264 * If an RPC based time service is not available then try the
1264 1265 * IP time service.
1265 1266 *
1266 1267 * This is for AUTH_DH processing. We will also pass down syncaddr
1267 1268 * and netname for NFS V4 even if AUTH_DH is not requested right now.
1268 1269 * NFS V4 does security negotiation in the kernel via SECINFO.
1269 1270 * These information might be needed later in the kernel.
1270 1271 *
1271 1272 * Eventurally, we want to move this code to nfs_clnt_secdata()
1272 1273 * when autod_nfs.c and mount.c can share the same get_the_addr()
1273 1274 * routine.
1274 1275 */
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1275 1276 flags = 0;
1276 1277 syncaddr = NULL;
1277 1278
1278 1279 if (nfs_sec.sc_rpcnum == AUTH_DH || vers == NFS_V4) {
1279 1280 /*
1280 1281 * If using the public fh or nfsv4, we will not contact the
1281 1282 * remote RPCBINDer, since it is possibly behind a firewall.
1282 1283 */
1283 1284 if (use_pubfh == FALSE && vers != NFS_V4) {
1284 1285 syncaddr = get_the_addr(hostname, RPCBPROG, RPCBVERS,
1285 - nconf, 0, NULL, NULL, FALSE, NULL, NULL);
1286 + nconf, 0, NULL, NULL, FALSE, NULL, NULL);
1286 1287 }
1287 1288
1288 1289 if (syncaddr != NULL) {
1289 1290 /* for flags in sec_data */
1290 1291 flags |= AUTH_F_RPCTIMESYNC;
1291 1292 } else {
1292 1293 struct nd_hostserv hs;
1293 1294 int error;
1294 1295
1295 1296 hs.h_host = hostname;
1296 1297 hs.h_serv = "timserver";
1297 1298
1298 1299 error = netdir_getbyname(nconf, &hs, &retaddrs);
1299 1300
1300 1301 if (error != ND_OK && (nfs_sec.sc_rpcnum == AUTH_DH)) {
1301 - pr_err(gettext("%s: secure: no time service\n"),
1302 - hostname);
1303 - return (-1);
1302 + pr_err(gettext("%s: secure: no time service\n"),
1303 + hostname);
1304 + return (-1);
1304 1305 }
1305 1306
1306 1307 if (error == ND_OK)
1307 1308 syncaddr = retaddrs->n_addrs;
1308 1309
1309 1310 /*
1310 1311 * For NFS_V4 if AUTH_DH is negotiated later in the
1311 1312 * kernel thru SECINFO, it will need syncaddr
1312 1313 * and netname data.
1313 1314 */
1314 1315 if (vers == NFS_V4 && syncaddr &&
1315 - host2netname(netname, hostname, NULL)) {
1316 - args->syncaddr = malloc(sizeof (struct netbuf));
1317 - args->syncaddr->buf = malloc(syncaddr->len);
1318 - (void) memcpy(args->syncaddr->buf, syncaddr->buf,
1319 - syncaddr->len);
1320 - args->syncaddr->len = syncaddr->len;
1321 - args->syncaddr->maxlen = syncaddr->maxlen;
1322 - args->netname = strdup(netname);
1323 - args->flags |= NFSMNT_SECURE;
1316 + host2netname(netname, hostname, NULL)) {
1317 + args->syncaddr = malloc(sizeof (struct netbuf));
1318 + args->syncaddr->buf = malloc(syncaddr->len);
1319 + (void) memcpy(args->syncaddr->buf,
1320 + syncaddr->buf, syncaddr->len);
1321 + args->syncaddr->len = syncaddr->len;
1322 + args->syncaddr->maxlen = syncaddr->maxlen;
1323 + args->netname = strdup(netname);
1324 + args->flags |= NFSMNT_SECURE;
1324 1325 }
1325 1326 }
1326 1327 }
1327 1328
1328 1329 /*
1329 1330 * For the initial chosen flavor (any flavor defined in nfssec.conf),
1330 1331 * the data will be stored in the sec_data structure via
1331 1332 * nfs_clnt_secdata() and be passed to the kernel via nfs_args_*
1332 1333 * extended data structure.
1333 1334 */
1334 1335 if (!(secdata = nfs_clnt_secdata(&nfs_sec, hostname, args->knconf,
1335 - syncaddr, flags))) {
1336 + syncaddr, flags))) {
1336 1337 pr_err(gettext("errors constructing security related data\n"));
1337 1338 if (flags & AUTH_F_RPCTIMESYNC) {
1338 1339 free(syncaddr->buf);
1339 1340 free(syncaddr);
1340 1341 } else if (retaddrs)
1341 1342 netdir_free((void *)retaddrs, ND_ADDRLIST);
1342 1343 return (-1);
1343 1344 }
1344 1345
1345 1346 NFS_ARGS_EXTB_secdata(args, secdata);
1346 1347 if (flags & AUTH_F_RPCTIMESYNC) {
1347 1348 free(syncaddr->buf);
1348 1349 free(syncaddr);
1349 1350 } else if (retaddrs)
1350 1351 netdir_free((void *)retaddrs, ND_ADDRLIST);
1351 1352 return (0);
1352 1353 }
1353 1354
1354 1355 /*
1355 1356 * Get the network address on "hostname" for program "prog"
1356 1357 * with version "vers" by using the nconf configuration data
1357 1358 * passed in.
1358 1359 *
1359 1360 * If the address of a netconfig pointer is null then
1360 1361 * information is not sufficient and no netbuf will be returned.
1361 1362 *
1362 1363 * Finally, ping the null procedure of that service.
1363 1364 *
1364 1365 * A similar routine is also defined in ../../autofs/autod_nfs.c.
1365 1366 * This is a potential routine to move to ../lib for common usage.
1366 1367 */
1367 1368 static struct netbuf *
1368 1369 get_the_addr(char *hostname, ulong_t prog, ulong_t vers,
1369 1370 struct netconfig *nconf, ushort_t port, struct t_info *tinfo,
1370 1371 caddr_t *fhp, bool_t get_pubfh, char *fspath, err_ret_t *error)
1371 1372 {
1372 1373 struct netbuf *nb = NULL;
1373 1374 struct t_bind *tbind = NULL;
1374 1375 CLIENT *cl = NULL;
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
1375 1376 struct timeval tv;
1376 1377 int fd = -1;
1377 1378 AUTH *ah = NULL;
1378 1379 AUTH *new_ah = NULL;
1379 1380 struct snego_t snego;
1380 1381
1381 1382 if (nconf == NULL)
1382 1383 return (NULL);
1383 1384
1384 1385 if ((fd = t_open(nconf->nc_device, O_RDWR, tinfo)) == -1)
1385 - goto done;
1386 + goto done;
1386 1387
1387 1388 /* LINTED pointer alignment */
1388 1389 if ((tbind = (struct t_bind *)t_alloc(fd, T_BIND, T_ADDR))
1389 - == NULL)
1390 + == NULL)
1390 1391 goto done;
1391 1392
1392 1393 /*
1393 1394 * In the case of public filehandle usage or NFSv4 we want to
1394 1395 * avoid use of the rpcbind/portmap protocol
1395 1396 */
1396 1397 if ((get_pubfh == TRUE) || (vers == NFS_V4)) {
1397 1398 struct nd_hostserv hs;
1398 1399 struct nd_addrlist *retaddrs;
1399 1400 int retval;
1400 1401 hs.h_host = hostname;
1401 1402
1402 1403 /* NFS where vers==4 does not support UDP */
1403 1404 if (vers == NFS_V4 &&
1404 1405 strncasecmp(nconf->nc_proto, NC_UDP,
1405 - strlen(NC_UDP)) == 0) {
1406 + strlen(NC_UDP)) == 0) {
1406 1407 SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
1407 1408 goto done;
1408 1409 }
1409 1410
1410 1411 if (port == 0)
1411 1412 hs.h_serv = "nfs";
1412 1413 else
1413 1414 hs.h_serv = NULL;
1414 1415
1415 1416 if ((retval = netdir_getbyname(nconf, &hs, &retaddrs))
1416 1417 != ND_OK) {
1417 1418 /*
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
1418 1419 * Carefully set the error value here. Want to signify
1419 1420 * that the error was an unknown host.
1420 1421 */
1421 1422 if (retval == ND_NOHOST) {
1422 1423 SET_ERR_RET(error, ERR_NOHOST, retval);
1423 1424 }
1424 1425
1425 1426 goto done;
1426 1427 }
1427 1428 memcpy(tbind->addr.buf, retaddrs->n_addrs->buf,
1428 - retaddrs->n_addrs->len);
1429 + retaddrs->n_addrs->len);
1429 1430 tbind->addr.len = retaddrs->n_addrs->len;
1430 1431 netdir_free((void *)retaddrs, ND_ADDRLIST);
1431 1432 (void) netdir_options(nconf, ND_SET_RESERVEDPORT, fd, NULL);
1432 1433
1433 1434 } else {
1434 1435 if (rpcb_getaddr(prog, vers, nconf, &tbind->addr,
1435 1436 hostname) == FALSE) {
1436 1437 goto done;
1437 1438 }
1438 1439 }
1439 1440
1440 1441 if (port) {
1441 1442 /* LINTED pointer alignment */
1442 1443 if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
1443 1444 ((struct sockaddr_in *)tbind->addr.buf)->sin_port
1444 - = port;
1445 + = port;
1445 1446 else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
1446 1447 ((struct sockaddr_in6 *)tbind->addr.buf)->sin6_port
1447 - = port;
1448 -
1448 + = port;
1449 1449 }
1450 1450
1451 1451 cl = clnt_tli_create(fd, nconf, &tbind->addr, prog, vers, 0, 0);
1452 1452 if (cl == NULL) {
1453 1453 /*
1454 1454 * clnt_tli_create() returns either RPC_SYSTEMERROR,
1455 1455 * RPC_UNKNOWNPROTO or RPC_TLIERROR. The RPC_TLIERROR translates
1456 1456 * to "Misc. TLI error". This is not too helpful. Most likely
1457 1457 * the connection to the remote server timed out, so this
1458 1458 * error is at least less perplexing.
1459 1459 * See: usr/src/cmd/rpcinfo/rpcinfo.c
1460 1460 */
1461 1461 if (rpc_createerr.cf_stat == RPC_TLIERROR) {
1462 1462 SET_ERR_RET(error, ERR_RPCERROR, RPC_PMAPFAILURE);
1463 1463 } else {
1464 1464 SET_ERR_RET(error, ERR_RPCERROR, rpc_createerr.cf_stat);
1465 1465 }
1466 1466 goto done;
1467 1467 }
1468 1468
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1469 1469 ah = authsys_create_default();
1470 1470 if (ah != NULL)
1471 1471 cl->cl_auth = ah;
1472 1472
1473 1473 tv.tv_sec = 5;
1474 1474 tv.tv_usec = 0;
1475 1475
1476 1476 (void) clnt_control(cl, CLSET_TIMEOUT, (char *)&tv);
1477 1477
1478 1478 if ((get_pubfh == TRUE) && (vers != NFS_V4)) {
1479 - enum snego_stat sec;
1479 + enum snego_stat sec;
1480 1480
1481 - if (!snego_done) {
1482 - /*
1483 - * negotiate sec flavor.
1484 - */
1485 - snego.cnt = 0;
1486 - if ((sec = nfs_sec_nego(vers, cl, fspath, &snego)) ==
1487 - SNEGO_SUCCESS) {
1488 - int jj;
1481 + if (!snego_done) {
1482 + /*
1483 + * negotiate sec flavor.
1484 + */
1485 + snego.cnt = 0;
1486 + if ((sec = nfs_sec_nego(vers, cl,
1487 + fspath, &snego)) == SNEGO_SUCCESS) {
1488 + int jj;
1489 1489
1490 - /*
1491 - * check if server supports the one
1492 - * specified in the sec= option.
1493 - */
1494 - if (sec_opt) {
1495 - for (jj = 0; jj < snego.cnt; jj++) {
1496 - if (snego.array[jj] == nfs_sec.sc_nfsnum) {
1497 - snego_done = TRUE;
1498 - break;
1499 - }
1500 - }
1501 - }
1502 -
1503 - /*
1504 - * find a common sec flavor
1505 - */
1506 - if (!snego_done) {
1507 - if (sec_opt) {
1508 - pr_err(gettext(
1509 - "Server does not support the security"
1510 - " flavor specified.\n"));
1511 - }
1512 - for (jj = 0; jj < snego.cnt; jj++) {
1513 - if (!nfs_getseconfig_bynumber(snego.array[jj],
1514 - &nfs_sec)) {
1515 - snego_done = TRUE;
1490 + /*
1491 + * check if server supports the one
1492 + * specified in the sec= option.
1493 + */
1516 1494 if (sec_opt) {
1517 - pr_err(gettext(
1518 - "Security flavor %d was negotiated and"
1519 - " will be used.\n"),
1520 - nfs_sec.sc_nfsnum);
1495 + for (jj = 0; jj < snego.cnt; jj++) {
1496 + if (snego.array[jj] ==
1497 + nfs_sec.sc_nfsnum) {
1498 + snego_done = TRUE;
1499 + break;
1500 + }
1501 + }
1521 1502 }
1522 - break;
1523 - }
1503 +
1504 + /*
1505 + * find a common sec flavor
1506 + */
1507 + if (!snego_done) {
1508 + if (sec_opt) {
1509 + pr_err(gettext(
1510 + "Server does not support"
1511 + " the security"
1512 + " flavor specified.\n"));
1513 + }
1514 +
1515 + for (jj = 0; jj < snego.cnt; jj++) {
1516 + if (!nfs_getseconfig_bynumber(
1517 + snego.array[jj],
1518 + &nfs_sec)) {
1519 + snego_done = TRUE;
1520 + if (sec_opt) {
1521 + pr_err(gettext(
1522 + "Security flavor %d was negotiated and will be used.\n"),
1523 + nfs_sec.
1524 + sc_nfsnum);
1525 + }
1526 +
1527 + break;
1528 + }
1529 + }
1530 +
1531 + if (!snego_done)
1532 + return (NULL);
1533 + }
1534 +
1535 + /*
1536 + * Now that the flavor has been
1537 + * negotiated, get the fh.
1538 + *
1539 + * First, create an auth handle using
1540 + * the negotiated sec flavor in the
1541 + * next lookup to fetch the filehandle.
1542 + */
1543 + new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
1544 + if (new_ah == NULL)
1545 + goto done;
1546 + cl->cl_auth = new_ah;
1547 + } else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
1548 + SNEGO_FAILURE) {
1549 + goto done;
1524 1550 }
1525 - }
1526 - if (!snego_done)
1527 - return (NULL);
1528 1551
1529 - /*
1530 - * Now that the flavor has been
1531 - * negotiated, get the fh.
1532 - *
1533 - * First, create an auth handle using the negotiated
1534 - * sec flavor in the next lookup to
1535 - * fetch the filehandle.
1536 - */
1537 - new_ah = nfs_create_ah(cl, hostname, &nfs_sec);
1538 - if (new_ah == NULL)
1539 - goto done;
1540 - cl->cl_auth = new_ah;
1541 - } else if (sec == SNEGO_ARRAY_TOO_SMALL || sec ==
1542 - SNEGO_FAILURE) {
1543 - goto done;
1552 + /*
1553 + * Note that if sec == SNEGO_DEF_VALID
1554 + * default sec flavor is acceptable.
1555 + * Use it to get the filehandle.
1556 + */
1544 1557 }
1545 - /*
1546 - * Note that if sec == SNEGO_DEF_VALID
1547 - * default sec flavor is acceptable.
1548 - * Use it to get the filehandle.
1549 - */
1550 - }
1551 1558
1552 - if (vers == NFS_VERSION) {
1553 - wnl_diropargs arg;
1554 - wnl_diropres *res;
1559 + if (vers == NFS_VERSION) {
1560 + wnl_diropargs arg;
1561 + wnl_diropres *res;
1555 1562
1556 - memset((char *)&arg.dir, 0, sizeof (wnl_fh));
1557 - arg.name = fspath;
1558 - res = wnlproc_lookup_2(&arg, cl);
1563 + memset((char *)&arg.dir, 0, sizeof (wnl_fh));
1564 + arg.name = fspath;
1565 + res = wnlproc_lookup_2(&arg, cl);
1559 1566
1560 - if (res == NULL || res->status != NFS_OK)
1561 - goto done;
1562 - *fhp = malloc(sizeof (wnl_fh));
1567 + if (res == NULL || res->status != NFS_OK)
1568 + goto done;
1569 + *fhp = malloc(sizeof (wnl_fh));
1563 1570
1564 - if (*fhp == NULL) {
1565 - pr_err(gettext("no memory\n"));
1566 - goto done;
1567 - }
1571 + if (*fhp == NULL) {
1572 + pr_err(gettext("no memory\n"));
1573 + goto done;
1574 + }
1568 1575
1569 - memcpy((char *)*fhp,
1570 - (char *)&res->wnl_diropres_u.wnl_diropres.file,
1571 - sizeof (wnl_fh));
1572 - } else {
1573 - WNL_LOOKUP3args arg;
1574 - WNL_LOOKUP3res *res;
1575 - nfs_fh3 *fh3p;
1576 + memcpy((char *)*fhp,
1577 + (char *)&res->wnl_diropres_u.wnl_diropres.file,
1578 + sizeof (wnl_fh));
1579 + } else {
1580 + WNL_LOOKUP3args arg;
1581 + WNL_LOOKUP3res *res;
1582 + nfs_fh3 *fh3p;
1576 1583
1577 - memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
1578 - arg.what.name = fspath;
1579 - res = wnlproc3_lookup_3(&arg, cl);
1584 + memset((char *)&arg.what.dir, 0, sizeof (wnl_fh3));
1585 + arg.what.name = fspath;
1586 + res = wnlproc3_lookup_3(&arg, cl);
1580 1587
1581 - if (res == NULL || res->status != NFS3_OK)
1582 - goto done;
1588 + if (res == NULL || res->status != NFS3_OK)
1589 + goto done;
1583 1590
1584 - fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
1591 + fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
1585 1592
1586 - if (fh3p == NULL) {
1587 - pr_err(gettext("no memory\n"));
1588 - CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);
1589 - goto done;
1590 - }
1593 + if (fh3p == NULL) {
1594 + pr_err(gettext("no memory\n"));
1595 + CLNT_FREERES(cl, xdr_WNL_LOOKUP3res,
1596 + (char *)res);
1597 + goto done;
1598 + }
1591 1599
1592 - fh3p->fh3_length =
1593 - res->WNL_LOOKUP3res_u.res_ok.object.data.data_len;
1594 - memcpy(fh3p->fh3_u.data,
1595 - res->WNL_LOOKUP3res_u.res_ok.object.data.data_val,
1596 - fh3p->fh3_length);
1600 + fh3p->fh3_length =
1601 + res->WNL_LOOKUP3res_u.res_ok.object.data.data_len;
1602 + memcpy(fh3p->fh3_u.data,
1603 + res->WNL_LOOKUP3res_u.res_ok.object.data.data_val,
1604 + fh3p->fh3_length);
1597 1605
1598 - *fhp = (caddr_t)fh3p;
1606 + *fhp = (caddr_t)fh3p;
1599 1607
1600 - CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);
1601 - }
1608 + CLNT_FREERES(cl, xdr_WNL_LOOKUP3res, (char *)res);
1609 + }
1602 1610 } else {
1603 1611 void *res;
1604 1612 struct rpc_err r_err;
1605 1613
1606 1614 if (vers == NFS_VERSION)
1607 - res = wnlproc_null_2(NULL, cl);
1615 + res = wnlproc_null_2(NULL, cl);
1608 1616 else if (vers == NFS_V3)
1609 - res = wnlproc3_null_3(NULL, cl);
1617 + res = wnlproc3_null_3(NULL, cl);
1610 1618 else
1611 - res = wnlproc4_null_4(NULL, cl);
1619 + res = wnlproc4_null_4(NULL, cl);
1612 1620
1613 1621 if (res == NULL) {
1614 1622 clnt_geterr(cl, &r_err);
1615 1623 if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
1616 1624 switch (r_err.re_status) {
1617 1625 case RPC_TLIERROR:
1618 1626 case RPC_CANTRECV:
1619 1627 case RPC_CANTSEND:
1620 1628 r_err.re_status = RPC_PROGVERSMISMATCH;
1621 1629 }
1622 1630 }
1623 1631 SET_ERR_RET(error, ERR_RPCERROR, r_err.re_status);
1624 1632 goto done;
1625 1633 }
1626 1634 }
1627 1635
1628 1636 /*
1629 1637 * Make a copy of the netbuf to return
1630 1638 */
1631 1639 nb = (struct netbuf *)malloc(sizeof (*nb));
1632 1640 if (nb == NULL) {
1633 1641 pr_err(gettext("no memory\n"));
1634 1642 goto done;
1635 1643 }
1636 1644 *nb = tbind->addr;
1637 1645 nb->buf = (char *)malloc(nb->maxlen);
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
1638 1646 if (nb->buf == NULL) {
1639 1647 pr_err(gettext("no memory\n"));
1640 1648 free(nb);
1641 1649 nb = NULL;
1642 1650 goto done;
1643 1651 }
1644 1652 (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len);
1645 1653
1646 1654 done:
1647 1655 if (cl) {
1648 - if (ah != NULL) {
1649 - if (new_ah != NULL)
1650 - AUTH_DESTROY(ah);
1651 - AUTH_DESTROY(cl->cl_auth);
1652 - cl->cl_auth = NULL;
1653 - }
1654 - clnt_destroy(cl);
1655 - cl = NULL;
1656 + if (ah != NULL) {
1657 + if (new_ah != NULL)
1658 + AUTH_DESTROY(ah);
1659 + AUTH_DESTROY(cl->cl_auth);
1660 + cl->cl_auth = NULL;
1661 + }
1662 + clnt_destroy(cl);
1663 + cl = NULL;
1656 1664 }
1657 1665 if (tbind) {
1658 1666 t_free((char *)tbind, T_BIND);
1659 1667 tbind = NULL;
1660 1668 }
1661 1669 if (fd >= 0)
1662 1670 (void) t_close(fd);
1663 1671 return (nb);
1664 1672 }
1665 1673
1666 1674 /*
1667 1675 * Get a network address on "hostname" for program "prog"
1668 1676 * with version "vers". If the port number is specified (non zero)
1669 1677 * then try for a TCP/UDP transport and set the port number of the
1670 1678 * resulting IP address.
1671 1679 *
1672 1680 * If the address of a netconfig pointer was passed and
1673 1681 * if it's not null, use it as the netconfig otherwise
1674 1682 * assign the address of the netconfig that was used to
1675 1683 * establish contact with the service.
1676 1684 *
1677 1685 * A similar routine is also defined in ../../autofs/autod_nfs.c.
1678 1686 * This is a potential routine to move to ../lib for common usage.
1679 1687 *
1680 1688 * "error" refers to a more descriptive term when get_addr fails
1681 1689 * and returns NULL: ERR_PROTO_NONE if no error introduced by
1682 1690 * -o proto option, ERR_NETPATH if error found in NETPATH
1683 1691 * environment variable, ERR_PROTO_INVALID if an unrecognized
1684 1692 * protocol is specified by user, and ERR_PROTO_UNSUPP for a
1685 1693 * recognized but invalid protocol (eg. ticlts, ticots, etc.).
1686 1694 * "error" is ignored if get_addr returns non-NULL result.
1687 1695 *
1688 1696 */
1689 1697 static struct netbuf *
1690 1698 get_addr(char *hostname, ulong_t prog, ulong_t vers, struct netconfig **nconfp,
1691 1699 char *proto, ushort_t port, struct t_info *tinfo, caddr_t *fhp,
1692 1700 bool_t get_pubfh, char *fspath, err_ret_t *error)
1693 1701 {
1694 1702 struct netbuf *nb = NULL;
1695 1703 struct netconfig *nconf = NULL;
1696 1704 NCONF_HANDLE *nc = NULL;
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
1697 1705 int nthtry = FIRST_TRY;
1698 1706 err_ret_t errsave_nohost, errsave_rpcerr;
1699 1707
1700 1708 SET_ERR_RET(&errsave_nohost, ERR_PROTO_NONE, 0);
1701 1709 SET_ERR_RET(&errsave_rpcerr, ERR_PROTO_NONE, 0);
1702 1710
1703 1711 SET_ERR_RET(error, ERR_PROTO_NONE, 0);
1704 1712
1705 1713 if (nconfp && *nconfp)
1706 1714 return (get_the_addr(hostname, prog, vers, *nconfp, port,
1707 - tinfo, fhp, get_pubfh, fspath, error));
1715 + tinfo, fhp, get_pubfh, fspath, error));
1708 1716 /*
1709 1717 * No nconf passed in.
1710 1718 *
1711 1719 * Try to get a nconf from /etc/netconfig filtered by
1712 1720 * the NETPATH environment variable.
1713 1721 * First search for COTS, second for CLTS unless proto
1714 1722 * is specified. When we retry, we reset the
1715 1723 * netconfig list so that we would search the whole list
1716 1724 * all over again.
1717 1725 */
1718 1726
1719 1727 if ((nc = setnetpath()) == NULL) {
1720 1728 /* should only return an error if problems with NETPATH */
1721 1729 /* In which case you are hosed */
1722 1730 SET_ERR_RET(error, ERR_NETPATH, 0);
1723 1731 goto done;
1724 1732 }
1725 1733
1726 1734 /*
1727 1735 * If proto is specified, then only search for the match,
1728 1736 * otherwise try COTS first, if failed, try CLTS.
1729 1737 */
1730 1738 if (proto) {
1731 1739 /* no matching proto name */
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
1732 1740 SET_ERR_RET(error, ERR_PROTO_INVALID, 0);
1733 1741
1734 1742 while (nconf = getnetpath(nc)) {
1735 1743 if (strcmp(nconf->nc_netid, proto))
1736 1744 continue;
1737 1745
1738 1746 /* may be unsupported */
1739 1747 SET_ERR_RET(error, ERR_PROTO_UNSUPP, 0);
1740 1748
1741 1749 if ((port != 0) &&
1742 - ((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1743 - strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1744 - (strcmp(nconf->nc_proto, NC_TCP) != 0 &&
1745 - strcmp(nconf->nc_proto, NC_UDP) != 0)))
1746 -
1750 + ((strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
1751 + strcmp(nconf->nc_protofmly, NC_INET6) == 0) &&
1752 + (strcmp(nconf->nc_proto, NC_TCP) != 0 &&
1753 + strcmp(nconf->nc_proto, NC_UDP) != 0))) {
1747 1754 continue;
1748 -
1749 - else {
1755 + } else {
1750 1756 nb = get_the_addr(hostname, prog,
1751 - vers, nconf, port, tinfo,
1752 - fhp, get_pubfh, fspath, error);
1757 + vers, nconf, port, tinfo,
1758 + fhp, get_pubfh, fspath, error);
1753 1759
1754 1760 if (nb != NULL)
1755 1761 break;
1756 1762
1757 1763 /* nb is NULL - deal with errors */
1758 1764 if (error) {
1759 1765 if (error->error_type == ERR_NOHOST)
1760 1766 SET_ERR_RET(&errsave_nohost,
1761 - error->error_type,
1762 - error->error_value);
1767 + error->error_type,
1768 + error->error_value);
1763 1769 if (error->error_type == ERR_RPCERROR)
1764 1770 SET_ERR_RET(&errsave_rpcerr,
1765 - error->error_type,
1766 - error->error_value);
1771 + error->error_type,
1772 + error->error_value);
1767 1773 }
1768 1774 /*
1769 1775 * continue with same protocol
1770 1776 * selection
1771 1777 */
1772 1778 continue;
1773 1779 }
1774 1780 } /* end of while */
1775 1781
1776 1782 if (nconf == NULL)
1777 1783 goto done;
1778 1784
1779 1785 if ((nb = get_the_addr(hostname, prog, vers, nconf, port,
1780 - tinfo, fhp, get_pubfh, fspath, error)) == NULL)
1786 + tinfo, fhp, get_pubfh, fspath, error)) == NULL)
1781 1787 goto done;
1782 -
1783 -
1784 1788 } else {
1785 1789 retry:
1786 1790 SET_ERR_RET(error, ERR_NETPATH, 0);
1787 1791 while (nconf = getnetpath(nc)) {
1788 1792 SET_ERR_RET(error, ERR_PROTO_NONE, 0);
1789 1793 if (nconf->nc_flag & NC_VISIBLE) {
1790 1794 if (nthtry == FIRST_TRY) {
1791 1795 if ((nconf->nc_semantics ==
1792 - NC_TPI_COTS_ORD) ||
1796 + NC_TPI_COTS_ORD) ||
1793 1797 (nconf->nc_semantics ==
1794 - NC_TPI_COTS)) {
1798 + NC_TPI_COTS)) {
1795 1799
1796 1800 if (port == 0)
1797 1801 break;
1798 1802
1799 1803 if ((strcmp(nconf->nc_protofmly,
1800 - NC_INET) == 0 ||
1801 - strcmp(nconf->
1802 - nc_protofmly,
1803 - NC_INET6) == 0) &&
1804 + NC_INET) == 0 ||
1805 + strcmp(nconf->nc_protofmly,
1806 + NC_INET6) == 0) &&
1804 1807 (strcmp(nconf->nc_proto,
1805 - NC_TCP) == 0))
1806 -
1808 + NC_TCP) == 0))
1807 1809 break;
1808 1810 }
1809 1811 }
1810 1812 if (nthtry == SECOND_TRY) {
1811 1813 if (nconf->nc_semantics ==
1812 - NC_TPI_CLTS) {
1814 + NC_TPI_CLTS) {
1813 1815 if (port == 0)
1814 1816 break;
1815 1817 if ((strcmp(nconf->nc_protofmly,
1816 - NC_INET) == 0 ||
1817 - strcmp(nconf->
1818 - nc_protofmly, NC_INET6)
1819 - == 0) &&
1820 - (strcmp(
1821 - nconf->nc_proto,
1822 - NC_UDP) == 0))
1818 + NC_INET) == 0 ||
1819 + strcmp(nconf->nc_protofmly,
1820 + NC_INET6) == 0) &&
1821 + (strcmp(nconf->nc_proto,
1822 + NC_UDP) == 0))
1823 1823 break;
1824 1824 }
1825 1825 }
1826 1826 }
1827 1827 } /* while */
1828 +
1828 1829 if (nconf == NULL) {
1829 1830 if (++nthtry <= MNT_PREF_LISTLEN) {
1830 1831 endnetpath(nc);
1831 1832 if ((nc = setnetpath()) == NULL)
1832 1833 goto done;
1833 1834 goto retry;
1834 1835 } else
1835 1836 goto done;
1836 1837 } else {
1837 1838 if ((nb = get_the_addr(hostname, prog, vers, nconf,
1838 - port, tinfo, fhp, get_pubfh, fspath, error))
1839 - == NULL) {
1839 + port, tinfo, fhp, get_pubfh, fspath, error))
1840 + == NULL) {
1841 +
1840 1842 /* nb is NULL - deal with errors */
1841 1843 if (error) {
1842 1844 if (error->error_type == ERR_NOHOST)
1843 1845 SET_ERR_RET(&errsave_nohost,
1844 - error->error_type,
1845 - error->error_value);
1846 + error->error_type,
1847 + error->error_value);
1846 1848 if (error->error_type == ERR_RPCERROR)
1847 1849 SET_ERR_RET(&errsave_rpcerr,
1848 - error->error_type,
1849 - error->error_value);
1850 + error->error_type,
1851 + error->error_value);
1850 1852 }
1851 1853 /*
1852 1854 * Continue the same search path in the
1853 1855 * netconfig db until no more matched
1854 1856 * nconf (nconf == NULL).
1855 1857 */
1856 1858 goto retry;
1857 1859 }
1858 1860 }
1859 1861 }
1860 1862 SET_ERR_RET(error, ERR_PROTO_NONE, 0);
1861 1863
1862 1864 /*
1863 1865 * Got nconf and nb. Now dup the netconfig structure (nconf)
1864 1866 * and return it thru nconfp.
1865 1867 */
1866 1868 *nconfp = getnetconfigent(nconf->nc_netid);
1867 1869 if (*nconfp == NULL) {
1868 1870 syslog(LOG_ERR, "no memory\n");
1869 1871 free(nb);
1870 1872 nb = NULL;
1871 1873 }
1872 1874 done:
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
1873 1875 if (nc)
1874 1876 endnetpath(nc);
1875 1877
1876 1878 if (nb == NULL) {
1877 1879 /*
1878 1880 * Check the saved errors. The RPC error has *
1879 1881 * precedence over the no host error.
1880 1882 */
1881 1883 if (errsave_nohost.error_type != ERR_PROTO_NONE)
1882 1884 SET_ERR_RET(error, errsave_nohost.error_type,
1883 - errsave_nohost.error_value);
1885 + errsave_nohost.error_value);
1884 1886
1885 1887 if (errsave_rpcerr.error_type != ERR_PROTO_NONE)
1886 1888 SET_ERR_RET(error, errsave_rpcerr.error_type,
1887 - errsave_rpcerr.error_value);
1889 + errsave_rpcerr.error_value);
1888 1890 }
1889 1891
1890 1892 return (nb);
1891 1893 }
1892 1894
1893 1895 /*
1894 1896 * Get a file handle usinging multi-component lookup with the public
1895 1897 * file handle.
1896 1898 */
1897 1899 static int
1898 1900 get_fh_via_pub(struct nfs_args *args, char *fshost, char *fspath, bool_t url,
1899 1901 bool_t loud, int *versp, struct netconfig **nconfp, ushort_t port)
1900 1902 {
1901 1903 uint_t vers_min;
1902 1904 uint_t vers_max;
1903 1905 int r;
1904 1906 char *path;
1905 1907
1906 1908 if (nfsvers != 0) {
1907 1909 vers_max = vers_min = nfsvers;
1908 1910 } else {
1909 1911 vers_max = vers_max_default;
1910 1912 vers_min = vers_min_default;
1911 1913 }
1912 1914
1913 1915 if (url == FALSE) {
1914 1916 path = malloc(strlen(fspath) + 2);
1915 1917 if (path == NULL) {
1916 1918 if (loud == TRUE) {
1917 1919 pr_err(gettext("no memory\n"));
1918 1920 }
1919 1921 return (RET_ERR);
1920 1922 }
1921 1923
1922 1924 path[0] = (char)WNL_NATIVEPATH;
1923 1925 (void) strcpy(&path[1], fspath);
1924 1926
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
1925 1927 } else {
1926 1928 path = fspath;
1927 1929 }
1928 1930
1929 1931 for (nfsvers_to_use = vers_max; nfsvers_to_use >= vers_min;
1930 1932 nfsvers_to_use--) {
1931 1933 /*
1932 1934 * getaddr_nfs will also fill in the fh for us.
1933 1935 */
1934 1936 r = getaddr_nfs(args, fshost, nconfp,
1935 - TRUE, path, port, NULL, FALSE);
1937 + TRUE, path, port, NULL, FALSE);
1936 1938
1937 1939 if (r == RET_OK) {
1938 1940 /*
1939 1941 * Since we are using the public fh, and NLM is
1940 1942 * not firewall friendly, use local locking.
1941 1943 * Not the case for v4.
1942 1944 */
1943 1945 *versp = nfsvers_to_use;
1944 1946 switch (nfsvers_to_use) {
1945 1947 case NFS_V4:
1946 1948 fstype = MNTTYPE_NFS4;
1947 1949 break;
1948 1950 case NFS_V3:
1949 1951 fstype = MNTTYPE_NFS3;
1950 1952 /* fall through to pick up llock option */
1951 1953 default:
1952 1954 args->flags |= NFSMNT_LLOCK;
1953 1955 break;
1954 1956 }
1955 1957 if (fspath != path)
1956 1958 free(path);
1957 1959
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
1958 1960 return (r);
1959 1961 }
1960 1962 }
1961 1963
1962 1964 if (fspath != path) {
1963 1965 free(path);
1964 1966 }
1965 1967
1966 1968 if (loud == TRUE) {
1967 1969 pr_err(gettext("Could not use public filehandle in request to"
1968 - " server %s\n"), fshost);
1970 + " server %s\n"), fshost);
1969 1971 }
1970 1972
1971 1973 return (r);
1972 1974 }
1973 1975
1974 1976 /*
1975 1977 * get fhandle of remote path from server's mountd
1976 1978 */
1977 1979 static int
1978 1980 get_fh(struct nfs_args *args, char *fshost, char *fspath, int *versp,
1979 1981 bool_t loud_on_mnt_err, struct netconfig **nconfp, ushort_t port)
1980 1982 {
1981 1983 static struct fhstatus fhs;
1982 1984 static struct mountres3 mountres3;
1983 1985 static struct pathcnf p;
1984 1986 nfs_fh3 *fh3p;
1985 1987 struct timeval timeout = { 25, 0};
1986 1988 CLIENT *cl;
1987 1989 enum clnt_stat rpc_stat;
1988 1990 rpcvers_t outvers = 0;
1989 1991 rpcvers_t vers_to_try;
1990 1992 rpcvers_t vers_min;
1991 1993 static int printed = 0;
1992 1994 int count, i, *auths;
1993 1995 char *msg;
1994 1996
1995 1997 switch (nfsvers) {
1996 1998 case 2: /* version 2 specified try that only */
1997 1999 vers_to_try = MOUNTVERS_POSIX;
1998 2000 vers_min = MOUNTVERS;
1999 2001 break;
2000 2002 case 3: /* version 3 specified try that only */
2001 2003 vers_to_try = MOUNTVERS3;
2002 2004 vers_min = MOUNTVERS3;
2003 2005 break;
2004 2006 case 4: /* version 4 specified try that only */
2005 2007 /*
2006 2008 * This assignment is in the wrong version sequence.
2007 2009 * The above are MOUNT program and this is NFS
2008 2010 * program. However, it happens to work out since the
2009 2011 * two don't collide for NFSv4.
2010 2012 */
2011 2013 vers_to_try = NFS_V4;
2012 2014 vers_min = NFS_V4;
2013 2015 break;
2014 2016 default: /* no version specified, start with default */
2015 2017 /*
2016 2018 * If the retry version is set, use that. This will
2017 2019 * be set if the last mount attempt returned any other
2018 2020 * besides an RPC error.
2019 2021 */
2020 2022 if (nfsretry_vers)
2021 2023 vers_to_try = nfsretry_vers;
2022 2024 else {
2023 2025 vers_to_try = vers_max_default;
2024 2026 vers_min = vers_min_default;
2025 2027 }
2026 2028
2027 2029 break;
2028 2030 }
2029 2031
2030 2032 /*
2031 2033 * In the case of version 4, just NULL proc the server since
2032 2034 * there is no MOUNT program. If this fails, then decrease
2033 2035 * vers_to_try and continue on with regular MOUNT program
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
2034 2036 * processing.
2035 2037 */
2036 2038 if (vers_to_try == NFS_V4) {
2037 2039 int savevers = nfsvers_to_use;
2038 2040 err_ret_t error;
2039 2041 int retval;
2040 2042 SET_ERR_RET(&error, ERR_PROTO_NONE, 0);
2041 2043
2042 2044 /* Let's hope for the best */
2043 2045 nfsvers_to_use = NFS_V4;
2044 - retval =
2045 - getaddr_nfs(args, fshost, nconfp, FALSE,
2046 - fspath, port, &error, vers_min == NFS_V4);
2046 + retval = getaddr_nfs(args, fshost, nconfp, FALSE,
2047 + fspath, port, &error, vers_min == NFS_V4);
2047 2048
2048 2049 if (retval == RET_OK) {
2049 2050 *versp = nfsvers_to_use = NFS_V4;
2050 2051 fstype = MNTTYPE_NFS4;
2051 2052 args->fh = strdup(fspath);
2052 2053 if (args->fh == NULL) {
2053 2054 pr_err(gettext("no memory\n"));
2054 2055 *versp = nfsvers_to_use = savevers;
2055 2056 return (RET_ERR);
2056 2057 }
2057 2058 return (RET_OK);
2058 2059 }
2059 2060 nfsvers_to_use = savevers;
2060 2061
2061 2062 vers_to_try--;
2062 2063 /* If no more versions to try, let the user know. */
2063 2064 if (vers_to_try < vers_min) {
2064 2065 return (retval);
2065 2066 }
2066 2067
2067 2068 /*
2068 2069 * If we are here, there are more versions to try but
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
2069 2070 * there has been an error of some sort. If it is not
2070 2071 * an RPC error (e.g. host unknown), we just stop and
2071 2072 * return the error since the other versions would see
2072 2073 * the same error as well.
2073 2074 */
2074 2075 if (retval == RET_ERR && error.error_type != ERR_RPCERROR)
2075 2076 return (retval);
2076 2077 }
2077 2078
2078 2079 while ((cl = clnt_create_vers(fshost, MOUNTPROG, &outvers,
2079 - vers_min, vers_to_try, "datagram_v")) == NULL) {
2080 + vers_min, vers_to_try, "datagram_v")) == NULL) {
2080 2081 if (rpc_createerr.cf_stat == RPC_UNKNOWNHOST) {
2081 2082 pr_err(gettext("%s: %s\n"), fshost,
2082 2083 clnt_spcreateerror(""));
2083 2084 return (RET_ERR);
2084 2085 }
2085 2086
2086 2087 /*
2087 2088 * We don't want to downgrade version on lost packets
2088 2089 */
2089 2090 if ((rpc_createerr.cf_stat == RPC_TIMEDOUT) ||
2090 - (rpc_createerr.cf_stat == RPC_PMAPFAILURE)) {
2091 + (rpc_createerr.cf_stat == RPC_PMAPFAILURE)) {
2091 2092 pr_err(gettext("%s: %s\n"), fshost,
2092 2093 clnt_spcreateerror(""));
2093 2094 return (RET_RETRY);
2094 2095 }
2095 2096
2096 2097 /*
2097 2098 * back off and try the previous version - patch to the
2098 2099 * problem of version numbers not being contigous and
2099 2100 * clnt_create_vers failing (SunOS4.1 clients & SGI servers)
2100 2101 * The problem happens with most non-Sun servers who
2101 2102 * don't support mountd protocol #2. So, in case the
2102 2103 * call fails, we re-try the call anyway.
2103 2104 */
2104 2105 vers_to_try--;
2105 2106 if (vers_to_try < vers_min) {
2106 2107 if (rpc_createerr.cf_stat == RPC_PROGVERSMISMATCH) {
2107 2108 if (nfsvers == 0) {
2108 2109 pr_err(gettext(
2109 2110 "%s:%s: no applicable versions of NFS supported\n"),
2110 2111 fshost, fspath);
2111 2112 } else {
2112 2113 pr_err(gettext(
2113 2114 "%s:%s: NFS Version %d not supported\n"),
2114 2115 fshost, fspath, nfsvers);
2115 2116 }
2116 2117 return (RET_ERR);
2117 2118 }
2118 2119 if (!printed) {
2119 2120 pr_err(gettext("%s: %s\n"), fshost,
2120 2121 clnt_spcreateerror(""));
2121 2122 printed = 1;
2122 2123 }
2123 2124 return (RET_RETRY);
2124 2125 }
2125 2126 }
2126 2127 if (posix && outvers < MOUNTVERS_POSIX) {
2127 2128 pr_err(gettext("%s: %s: no pathconf info\n"),
2128 2129 fshost, clnt_sperror(cl, ""));
2129 2130 clnt_destroy(cl);
2130 2131 return (RET_ERR);
2131 2132 }
2132 2133
2133 2134 if (__clnt_bindresvport(cl) < 0) {
2134 2135 pr_err(gettext("Couldn't bind to reserved port\n"));
2135 2136 clnt_destroy(cl);
2136 2137 return (RET_RETRY);
2137 2138 }
2138 2139
2139 2140 if ((cl->cl_auth = authsys_create_default()) == NULL) {
2140 2141 pr_err(
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
2141 2142 gettext("Couldn't create default authentication handle\n"));
2142 2143 clnt_destroy(cl);
2143 2144 return (RET_RETRY);
2144 2145 }
2145 2146
2146 2147 switch (outvers) {
2147 2148 case MOUNTVERS:
2148 2149 case MOUNTVERS_POSIX:
2149 2150 *versp = nfsvers_to_use = NFS_VERSION;
2150 2151 rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2151 - (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
2152 + (caddr_t)&fspath, xdr_fhstatus, (caddr_t)&fhs, timeout);
2152 2153 if (rpc_stat != RPC_SUCCESS) {
2153 2154 pr_err(gettext("%s:%s: server not responding %s\n"),
2154 2155 fshost, fspath, clnt_sperror(cl, ""));
2155 2156 clnt_destroy(cl);
2156 2157 return (RET_RETRY);
2157 2158 }
2158 2159
2159 2160 if ((errno = fhs.fhs_status) != MNT_OK) {
2160 2161 if (loud_on_mnt_err) {
2161 - if (errno == EACCES) {
2162 - pr_err(gettext("%s:%s: access denied\n"),
2163 - fshost, fspath);
2164 - } else {
2165 - pr_err(gettext("%s:%s: %s\n"), fshost, fspath,
2166 - strerror(errno));
2167 - }
2162 + if (errno == EACCES) {
2163 + pr_err(gettext(
2164 + "%s:%s: access denied\n"),
2165 + fshost, fspath);
2166 + } else {
2167 + pr_err(gettext("%s:%s: %s\n"),
2168 + fshost, fspath, strerror(errno));
2169 + }
2168 2170 }
2169 2171 clnt_destroy(cl);
2170 2172 return (RET_MNTERR);
2171 2173 }
2172 2174 args->fh = malloc(sizeof (fhs.fhstatus_u.fhs_fhandle));
2173 2175 if (args->fh == NULL) {
2174 2176 pr_err(gettext("no memory\n"));
2175 2177 return (RET_ERR);
2176 2178 }
2177 2179 memcpy((caddr_t)args->fh, (caddr_t)&fhs.fhstatus_u.fhs_fhandle,
2178 - sizeof (fhs.fhstatus_u.fhs_fhandle));
2180 + sizeof (fhs.fhstatus_u.fhs_fhandle));
2179 2181 if (!errno && posix) {
2180 2182 rpc_stat = clnt_call(cl, MOUNTPROC_PATHCONF,
2181 - xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
2182 - (caddr_t)&p, timeout);
2183 + xdr_dirpath, (caddr_t)&fspath, xdr_ppathcnf,
2184 + (caddr_t)&p, timeout);
2183 2185 if (rpc_stat != RPC_SUCCESS) {
2184 2186 pr_err(gettext(
2185 2187 "%s:%s: server not responding %s\n"),
2186 2188 fshost, fspath, clnt_sperror(cl, ""));
2187 2189 free(args->fh);
2188 2190 clnt_destroy(cl);
2189 2191 return (RET_RETRY);
2190 2192 }
2191 2193 if (_PC_ISSET(_PC_ERROR, p.pc_mask)) {
2192 2194 pr_err(gettext(
2193 2195 "%s:%s: no pathconf info\n"),
2194 2196 fshost, fspath);
2195 2197 free(args->fh);
2196 2198 clnt_destroy(cl);
2197 2199 return (RET_ERR);
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
2198 2200 }
2199 2201 args->flags |= NFSMNT_POSIX;
2200 2202 args->pathconf = malloc(sizeof (p));
2201 2203 if (args->pathconf == NULL) {
2202 2204 pr_err(gettext("no memory\n"));
2203 2205 free(args->fh);
2204 2206 clnt_destroy(cl);
2205 2207 return (RET_ERR);
2206 2208 }
2207 2209 memcpy((caddr_t)args->pathconf, (caddr_t)&p,
2208 - sizeof (p));
2210 + sizeof (p));
2209 2211 }
2210 2212 break;
2211 2213
2212 2214 case MOUNTVERS3:
2213 2215 *versp = nfsvers_to_use = NFS_V3;
2214 2216 rpc_stat = clnt_call(cl, MOUNTPROC_MNT, xdr_dirpath,
2215 - (caddr_t)&fspath,
2216 - xdr_mountres3, (caddr_t)&mountres3, timeout);
2217 + (caddr_t)&fspath, xdr_mountres3,
2218 + (caddr_t)&mountres3, timeout);
2217 2219 if (rpc_stat != RPC_SUCCESS) {
2218 2220 pr_err(gettext("%s:%s: server not responding %s\n"),
2219 2221 fshost, fspath, clnt_sperror(cl, ""));
2220 2222 clnt_destroy(cl);
2221 2223 return (RET_RETRY);
2222 2224 }
2223 2225
2224 2226 /*
2225 2227 * Assume here that most of the MNT3ERR_*
2226 2228 * codes map into E* errors.
2227 2229 */
2228 2230 if ((errno = mountres3.fhs_status) != MNT_OK) {
2229 - if (loud_on_mnt_err) {
2230 - switch (errno) {
2231 - case MNT3ERR_NAMETOOLONG:
2232 - msg = "path name is too long";
2233 - break;
2234 - case MNT3ERR_NOTSUPP:
2235 - msg = "operation not supported";
2236 - break;
2237 - case MNT3ERR_SERVERFAULT:
2238 - msg = "server fault";
2239 - break;
2240 - default:
2241 - msg = strerror(errno);
2242 - break;
2231 + if (loud_on_mnt_err) {
2232 + switch (errno) {
2233 + case MNT3ERR_NAMETOOLONG:
2234 + msg = "path name is too long";
2235 + break;
2236 + case MNT3ERR_NOTSUPP:
2237 + msg = "operation not supported";
2238 + break;
2239 + case MNT3ERR_SERVERFAULT:
2240 + msg = "server fault";
2241 + break;
2242 + default:
2243 + msg = strerror(errno);
2244 + break;
2245 + }
2246 +
2247 + pr_err(gettext("%s:%s: %s\n"),
2248 + fshost, fspath, msg);
2243 2249 }
2244 - pr_err(gettext("%s:%s: %s\n"), fshost, fspath, msg);
2245 - }
2246 - clnt_destroy(cl);
2247 - return (RET_MNTERR);
2250 +
2251 + clnt_destroy(cl);
2252 + return (RET_MNTERR);
2248 2253 }
2249 2254
2250 2255 fh3p = (nfs_fh3 *)malloc(sizeof (*fh3p));
2251 2256 if (fh3p == NULL) {
2252 2257 pr_err(gettext("no memory\n"));
2253 2258 return (RET_ERR);
2254 2259 }
2255 2260 fh3p->fh3_length =
2256 - mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
2261 + mountres3.mountres3_u.mountinfo.fhandle.fhandle3_len;
2257 2262 (void) memcpy(fh3p->fh3_u.data,
2258 - mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
2259 - fh3p->fh3_length);
2263 + mountres3.mountres3_u.mountinfo.fhandle.fhandle3_val,
2264 + fh3p->fh3_length);
2260 2265 args->fh = (caddr_t)fh3p;
2261 2266 fstype = MNTTYPE_NFS3;
2262 2267
2263 2268 /*
2264 2269 * Check the security flavor to be used.
2265 2270 *
2266 2271 * If "secure" or "sec=flavor" is a mount
2267 2272 * option, check if the server supports the "flavor".
2268 2273 * If the server does not support the flavor, return
2269 2274 * error.
2270 2275 *
2271 2276 * If no mount option is given then use the first supported
2272 2277 * security flavor (by the client) in the auth list returned
2273 2278 * from the server.
2274 2279 *
2275 2280 */
2276 2281 auths =
2277 - mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val;
2282 + mountres3.mountres3_u.mountinfo.auth_flavors.
2283 + auth_flavors_val;
2278 2284 count =
2279 - mountres3.mountres3_u.mountinfo.auth_flavors.auth_flavors_len;
2285 + mountres3.mountres3_u.mountinfo.auth_flavors.
2286 + auth_flavors_len;
2280 2287
2281 2288 if (sec_opt) {
2282 2289 for (i = 0; i < count; i++) {
2283 2290 if (auths[i] == nfs_sec.sc_nfsnum)
2284 - break;
2291 + break;
2285 2292 }
2286 - if (i >= count) {
2293 + if (i >= count)
2287 2294 goto autherr;
2288 - }
2289 2295 } else {
2290 - if (count > 0) {
2291 - for (i = 0; i < count; i++) {
2292 - if (!nfs_getseconfig_bynumber(auths[i], &nfs_sec)) {
2293 - sec_opt++;
2294 - break;
2295 - }
2296 + if (count > 0) {
2297 + for (i = 0; i < count; i++) {
2298 + if (!nfs_getseconfig_bynumber(auths[i],
2299 + &nfs_sec)) {
2300 + sec_opt++;
2301 + break;
2302 + }
2303 + }
2304 +
2305 + if (i >= count)
2306 + goto autherr;
2296 2307 }
2297 - if (i >= count) {
2298 - goto autherr;
2299 - }
2300 - }
2301 2308 }
2302 2309 break;
2303 2310 default:
2304 2311 pr_err(gettext("%s:%s: Unknown MOUNT version %d\n"),
2305 2312 fshost, fspath, outvers);
2306 2313 clnt_destroy(cl);
2307 2314 return (RET_ERR);
2308 2315 }
2309 2316
2310 2317 clnt_destroy(cl);
2311 2318 return (RET_OK);
2312 2319
2313 2320 autherr:
2314 2321 pr_err(gettext(
2315 - "security mode does not match the server exporting %s:%s\n"),
2316 - fshost, fspath);
2322 + "security mode does not match the server exporting %s:%s\n"),
2323 + fshost, fspath);
2317 2324 clnt_destroy(cl);
2318 2325 return (RET_ERR);
2319 2326 }
2320 2327
2321 2328 /*
2322 2329 * Fill in the address for the server's NFS service and
2323 2330 * fill in a knetconfig structure for the transport that
2324 2331 * the service is available on.
2325 2332 */
2326 2333 static int
2327 2334 getaddr_nfs(struct nfs_args *args, char *fshost, struct netconfig **nconfp,
2328 2335 bool_t get_pubfh, char *fspath, ushort_t port, err_ret_t *error,
2329 2336 bool_t print_rpcerror)
2330 2337 {
2331 2338 struct stat sb;
2332 2339 struct netconfig *nconf;
2333 2340 struct knetconfig *knconfp;
2334 2341 static int printed = 0;
2335 2342 struct t_info tinfo;
2336 2343 err_ret_t addr_error;
2337 2344
2338 2345 SET_ERR_RET(error, ERR_PROTO_NONE, 0);
2339 2346 SET_ERR_RET(&addr_error, ERR_PROTO_NONE, 0);
2340 2347
2341 2348 if (nfs_proto) {
2342 2349 /*
2343 2350 * If a proto is specified and its rdma try this. The kernel
2344 2351 * will later do the reachablity test and fail form there
2345 2352 * if rdma transport is not available to kernel rpc
2346 2353 */
2347 2354 if (strcmp(nfs_proto, "rdma") == 0) {
2348 2355 args->addr = get_addr(fshost, NFS_PROGRAM,
2349 2356 nfsvers_to_use, nconfp, NULL, port, &tinfo,
2350 2357 &args->fh, get_pubfh, fspath, &addr_error);
2351 2358
2352 2359 args->flags |= NFSMNT_DORDMA;
2353 2360 } else {
2354 2361 args->addr = get_addr(fshost, NFS_PROGRAM,
2355 2362 nfsvers_to_use, nconfp, nfs_proto, port, &tinfo,
2356 2363 &args->fh, get_pubfh, fspath, &addr_error);
2357 2364 }
2358 2365 } else {
2359 2366 args->addr = get_addr(fshost, NFS_PROGRAM, nfsvers_to_use,
2360 2367 nconfp, nfs_proto, port, &tinfo, &args->fh, get_pubfh,
2361 2368 fspath, &addr_error);
2362 2369 /*
2363 2370 * If no proto is specified set this flag.
2364 2371 * Kernel mount code will try to use RDMA if its on the
2365 2372 * system, otherwise it will keep on using the protocol
2366 2373 * selected here, through the above get_addr call.
2367 2374 */
2368 2375 if (nfs_proto == NULL)
2369 2376 args->flags |= NFSMNT_TRYRDMA;
2370 2377 }
2371 2378
2372 2379 if (args->addr == NULL) {
2373 2380 /*
2374 2381 * We could have failed because the server had no public
2375 2382 * file handle support. So don't print a message and don't
2376 2383 * retry.
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
2377 2384 */
2378 2385 if (get_pubfh == TRUE)
2379 2386 return (RET_ERR);
2380 2387
2381 2388 if (!printed) {
2382 2389 switch (addr_error.error_type) {
2383 2390 case 0:
2384 2391 printed = 1;
2385 2392 break;
2386 2393 case ERR_RPCERROR:
2394 + /* no error print at this time */
2387 2395 if (!print_rpcerror)
2388 - /* no error print at this time */
2389 2396 break;
2390 2397 pr_err(gettext("%s NFS service not"
2391 - " available %s\n"), fshost,
2398 + " available %s\n"), fshost,
2392 2399 clnt_sperrno(addr_error.error_value));
2393 2400 printed = 1;
2394 2401 break;
2395 2402 case ERR_NETPATH:
2396 2403 pr_err(gettext("%s: Error in NETPATH.\n"),
2397 - fshost);
2404 + fshost);
2398 2405 printed = 1;
2399 2406 break;
2400 2407 case ERR_PROTO_INVALID:
2401 2408 pr_err(gettext("%s: NFS service does not"
2402 - " recognize protocol: %s.\n"), fshost,
2403 - nfs_proto);
2409 + " recognize protocol: %s.\n"), fshost,
2410 + nfs_proto);
2404 2411 printed = 1;
2405 2412 break;
2406 2413 case ERR_PROTO_UNSUPP:
2407 2414 if (nfsvers || nfsvers_to_use == NFS_VERSMIN) {
2408 2415 /*
2409 2416 * Don't set "printed" here. Since we
2410 2417 * have to keep checking here till we
2411 2418 * exhaust transport errors on all vers.
2412 2419 *
2413 2420 * Print this message if:
2414 2421 * 1. After we have tried all versions
2415 2422 * of NFS and none support the asked
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
2416 2423 * transport.
2417 2424 *
2418 2425 * 2. If a version is specified and it
2419 2426 * does'nt support the asked
2420 2427 * transport.
2421 2428 *
2422 2429 * Otherwise we decrement the version
2423 2430 * and retry below.
2424 2431 */
2425 2432 pr_err(gettext("%s: NFS service does"
2426 - " not support protocol: %s.\n"),
2427 - fshost, nfs_proto);
2433 + " not support protocol: %s.\n"),
2434 + fshost, nfs_proto);
2428 2435 }
2429 2436 break;
2430 2437 case ERR_NOHOST:
2431 2438 pr_err("%s: %s\n", fshost, "Unknown host");
2432 2439 printed = 1;
2433 2440 break;
2434 2441 default:
2435 2442 /* case ERR_PROTO_NONE falls through */
2436 2443 pr_err(gettext("%s: NFS service not responding"
2437 - "\n"), fshost);
2444 + "\n"), fshost);
2438 2445 printed = 1;
2439 2446 break;
2440 2447 }
2441 2448 }
2449 +
2442 2450 SET_ERR_RET(error,
2443 - addr_error.error_type, addr_error.error_value);
2451 + addr_error.error_type, addr_error.error_value);
2444 2452 if (addr_error.error_type == ERR_PROTO_NONE)
2445 2453 return (RET_RETRY);
2446 2454 else if (addr_error.error_type == ERR_RPCERROR &&
2447 - ! IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
2455 + ! IS_UNRECOVERABLE_RPC(addr_error.error_value)) {
2448 2456 return (RET_RETRY);
2449 2457 } else if (nfsvers == 0 && addr_error.error_type ==
2450 - ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
2458 + ERR_PROTO_UNSUPP && nfsvers_to_use != NFS_VERSMIN) {
2451 2459 /*
2452 2460 * If no version is specified, and the error is due
2453 2461 * to an unsupported transport, then decrement the
2454 2462 * version and retry.
2455 2463 */
2456 2464 return (RET_RETRY);
2457 2465 } else
2458 2466 return (RET_ERR);
2459 2467 }
2460 2468 nconf = *nconfp;
2461 2469
2462 2470 if (stat(nconf->nc_device, &sb) < 0) {
2463 2471 pr_err(gettext("getaddr_nfs: couldn't stat: %s: %s\n"),
2464 2472 nconf->nc_device, strerror(errno));
2465 2473 return (RET_ERR);
2466 2474 }
2467 2475
2468 2476 knconfp = (struct knetconfig *)malloc(sizeof (*knconfp));
2469 2477 if (!knconfp) {
2470 2478 pr_err(gettext("no memory\n"));
2471 2479 return (RET_ERR);
2472 2480 }
2473 2481 knconfp->knc_semantics = nconf->nc_semantics;
2474 2482 knconfp->knc_protofmly = nconf->nc_protofmly;
2475 2483 knconfp->knc_proto = nconf->nc_proto;
2476 2484 knconfp->knc_rdev = sb.st_rdev;
2477 2485
2478 2486 /* make sure we don't overload the transport */
2479 2487 if (tinfo.tsdu > 0 && tinfo.tsdu < NFS_MAXDATA + NFS_RPC_HDR) {
2480 2488 args->flags |= (NFSMNT_RSIZE | NFSMNT_WSIZE);
2481 2489 if (args->rsize == 0 || args->rsize > tinfo.tsdu - NFS_RPC_HDR)
2482 2490 args->rsize = tinfo.tsdu - NFS_RPC_HDR;
2483 2491 if (args->wsize == 0 || args->wsize > tinfo.tsdu - NFS_RPC_HDR)
2484 2492 args->wsize = tinfo.tsdu - NFS_RPC_HDR;
2485 2493 }
2486 2494
2487 2495 args->flags |= NFSMNT_KNCONF;
2488 2496 args->knconf = knconfp;
2489 2497 return (RET_OK);
2490 2498 }
2491 2499
2492 2500 static int
2493 2501 retry(struct mnttab *mntp, int ro)
2494 2502 {
2495 2503 int delay = 5;
2496 2504 int count = retries;
2497 2505 int r;
2498 2506
2499 2507 /*
2500 2508 * Please see comments on nfsretry_vers in the beginning of this file
2501 2509 * and in main() routine.
2502 2510 */
2503 2511
2504 2512 if (bg) {
2505 2513 if (fork() > 0)
2506 2514 return (RET_OK);
2507 2515 pr_err(gettext("backgrounding: %s\n"), mntp->mnt_mountp);
2508 2516 backgrounded = 1;
2509 2517 } else {
2510 2518 if (!nfsretry_vers)
2511 2519 pr_err(gettext("retrying: %s\n"), mntp->mnt_mountp);
2512 2520 }
↓ open down ↓ |
52 lines elided |
↑ open up ↑ |
2513 2521
2514 2522 while (count--) {
2515 2523 if ((r = mount_nfs(mntp, ro, NULL)) == RET_OK) {
2516 2524 pr_err(gettext("%s: mounted OK\n"), mntp->mnt_mountp);
2517 2525 return (RET_OK);
2518 2526 }
2519 2527 if (r != RET_RETRY)
2520 2528 break;
2521 2529
2522 2530 if (count > 0) {
2523 - (void) sleep(delay);
2524 - delay *= 2;
2525 - if (delay > 120)
2526 - delay = 120;
2531 + (void) sleep(delay);
2532 + delay *= 2;
2533 + if (delay > 120)
2534 + delay = 120;
2527 2535 }
2528 2536 }
2529 2537
2530 2538 if (!nfsretry_vers)
2531 2539 pr_err(gettext("giving up on: %s\n"), mntp->mnt_mountp);
2532 2540
2533 2541 return (RET_ERR);
2534 2542 }
2535 2543
2536 2544 /*
2537 2545 * Read the /etc/default/nfs configuration file to determine if the
2538 2546 * client has been configured for a new min/max for the NFS version to
2539 2547 * use.
2540 2548 */
2541 2549 static void
2542 2550 read_default(void)
2543 2551 {
2544 2552 char *defval;
2545 2553 int errno;
2546 2554 int tmp;
2547 2555
2548 2556 /* Fail silently if error in opening the default nfs config file */
2549 2557 if ((defopen(NFSADMIN)) == 0) {
2550 2558 if ((defval = defread("NFS_CLIENT_VERSMIN=")) != NULL) {
2551 2559 errno = 0;
2552 2560 tmp = strtol(defval, (char **)NULL, 10);
2553 2561 if (errno == 0) {
2554 2562 vers_min_default = tmp;
2555 2563 }
2556 2564 }
2557 2565 if ((defval = defread("NFS_CLIENT_VERSMAX=")) != NULL) {
2558 2566 errno = 0;
2559 2567 tmp = strtol(defval, (char **)NULL, 10);
2560 2568 if (errno == 0) {
2561 2569 vers_max_default = tmp;
2562 2570 }
2563 2571 }
2564 2572 /* close defaults file */
2565 2573 defopen(NULL);
2566 2574 }
2567 2575 }
2568 2576
2569 2577 static void
2570 2578 sigusr1(int s)
2571 2579 {
2572 2580 }
↓ open down ↓ |
36 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX