share.c revision 7f7322febbcfe774b7270abc3b191c094bfcc517
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* University Copyright- Copyright (c) 1982, 1986, 1988
* The Regents of the University of California
* All Rights Reserved
*
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* nfs share
*/
#define _REENTRANT
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <netconfig.h>
#include <netdir.h>
#include <locale.h>
#include <zone.h>
#include <rpcsvc/daemon_utils.h>
#include "../lib/nfslog_config.h"
#include "../lib/sharetab.h"
#include "../lib/nfslogtab.h"
#define RET_OK 0
#define RET_ERR 32
static void configlog(struct exportdata *, char *);
static int direq(char *, char *);
static int newopts(char *);
static void parseopts_old(struct exportdata *, char *);
static void parseopts_new(struct exportdata *, char *);
static void pr_err(char *, ...);
static int shareable(char *);
static int sharetab_add(char *, char *, char *, char *, int);
static int sharepub_exist(char *);
static void usage();
static void exportindex(struct exportdata *, char *);
static int nfslogtab_add(char *, char *, char *);
static int nfslogtab_deactivate(char *);
extern int issubdir();
extern int exportfs();
int nfs_getseconfig_byname(char *, seconfig_t *);
static void printarg(char *, struct exportdata *);
static struct exportdata ex;
/*
* list of support services needed
*/
static char *service_list[] =
int
{
extern int optind;
extern char *optarg;
char dir[MAXPATHLEN];
char *res = "-";
char *opts = "rw";
char *descr = "";
char *services;
int c;
int replace = 0;
int verbose = 0;
/* Don't drop core if the NFS module isn't loaded. */
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
switch (c) {
case 'o':
break;
case 'd':
break;
case 'v':
verbose++;
break;
default:
usage();
}
}
usage();
}
case 0:
break;
case 1:
break;
case 2:
replace = 1;
break;
}
}
else
/*
* If -o public was specified, check for any existing directory
* shared with -o public. If so, fail.
*/
errno = 0;
gettext("Cannot share more than filesystem with"
" 'public' option\n"));
}
}
if (verbose)
switch (errno) {
case EREMOTE:
dir);
break;
case EPERM:
if (getzoneid() != GLOBAL_ZONEID) {
"in non-global zones: %s\n"),
dir);
break;
}
/* FALLTHRU */
default:
break;
}
}
/*
* enable services as needed.
*/
return (RET_OK);
}
/*
* Check if there already is an entry shared with -o public.
*/
static int
sharepub_exist(char *dir)
{
int res;
FILE *f;
char *val;
if (f == NULL) {
return (0);
}
continue;
continue;
return (1);
}
}
if (res < 0) {
(void) fclose(f);
}
(void) fclose(f);
return (0);
}
/*
* Check the nfs share entries in sharetab file.
* Returns:
* 0 dir not shareable
* 1 dir is shareable
* 2 dir is already shared (can modify options)
*/
static int
char *path;
{
FILE *f;
int res;
errno = 0;
if (*path != '/')
/*
* We make the assumption that if we can't open the SHARETAB
* file for some reason other than it doesn't exist, then we
* won't share the directory. Since we can't complete the
* operation correctly, then let's not do it at all.
*/
if (f == NULL) {
return (1);
return (0);
}
continue;
(void) fclose(f);
return (2);
}
"(%s) already shared\n"),
}
"(%s) already shared\n"),
}
}
if (res < 0)
(void) fclose(f);
return (1);
}
static int
{
return (1);
return (0);
}
static char *optlist[] = {
#define OPT_RO 0
#define OPT_RW 1
#define OPT_ROOT 2
#define OPT_SECURE 3
#define OPT_ANON 4
#define OPT_WINDOW 5
#define OPT_NOSUID 6
#define OPT_ACLOK 7
#define OPT_NOSUB 8
#define OPT_SEC 9
#define OPT_PUBLIC 10
#define OPT_INDEX 11
#define OPT_LOG 12
#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
#define OPT_VOLFH 13
#endif /* VOLATILE_FH_TEST */
};
/*
* If the option string contains a "sec="
* option, then use new option syntax.
*/
static int
{
char *p, *val;
if (p == NULL)
while (*p)
return (1);
return (0);
}
#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
/*
* Set the ex_flags to indicate which fh expire type. Return 0 for success,
* error otherwise.
*/
static int
{
int err = 0;
*next = '\0';
else {
}
*next = ':';
}
return (err);
}
#endif /* VOLATILE_FH_TEST */
#define DEF_WIN 30000
/*
* Parse the share options from the "-o" flag.
* The extracted data is moved into the exports
* structure which is passed into the kernel via
* the exportfs() system call.
*/
static void
{
int done_aclok = 0;
int done_nosuid = 0;
int done_anon = 0;
if (p == NULL)
/*
* Initialize some fields
*/
while (*p) {
savep = p;
case OPT_RO:
break;
case OPT_RW:
break;
case OPT_ROOT:
break;
case OPT_SECURE:
}
break;
case OPT_ANON:
if (done_anon++)
if (!val) {
}
/* check for special "-1" value, which is ok */
}
break;
case OPT_WINDOW:
break;
case OPT_NOSUID:
if (done_nosuid++)
break;
case OPT_ACLOK:
if (done_aclok++)
break;
case OPT_NOSUB:
/*
* The "don't allow mount of subdirectories" option.
*/
break;
case OPT_PUBLIC:
break;
case OPT_INDEX:
break;
case OPT_LOG:
break;
#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
case OPT_VOLFH:
/* volatile filehandles - expire on share */
break;
#endif /* VOLATILE_FH_TEST */
default:
}
}
}
/*
* Set uninitialized flags to "rw"
*/
}
/*
* Parse the new share options from the "-o" flag.
* Parsing is more complicated than the old case
* Since we may be setting up multiple secinfo entries.
* Syntax is more restrictive: the flavor-dependent
* options: ro, rw, root, window can only follow
* a sec option.
*/
static void
{
char *f, *lasts;
int i, secopt;
int count = 0;
int done_aclok = 0;
int done_nosuid = 0;
int done_anon = 0;
if (p == NULL)
/*
* Count the number of security modes
*/
while (*p) {
case OPT_SECURE:
"secure and sec\n"));
break;
case OPT_SEC:
count++;
for (q = val; *q; q++)
if (*q == ':')
count++;
break;
}
}
/*
* Initialize some fields
*/
for (i = 0; i < count; i++) {
}
if (p == NULL)
secopt = 0;
while (*p) {
savep = p;
case OPT_SEC:
if (secopt)
sp++;
secopt++;
" \"%s\"\n"), f);
if (lasts)
sp++;
}
break;
case OPT_RO:
if (secopt == 0)
break;
case OPT_RW:
if (secopt == 0)
break;
case OPT_ROOT:
if (secopt == 0)
"root\n"));
/*
* Can treat AUTH_UNIX root lists
* as a special case and have
* the nfsauth service check the
* list just like any other access
* list, i.e. supports netgroups,
* domain suffixes, etc.
*/
continue;
/*
* Root lists for other sec types
* need to be checked in the
* kernel. Build a list of names
* to be fed into the kernel via
* exportfs().
*/
pt->s_rootnames =
}
break;
case OPT_WINDOW:
if (secopt == 0)
"window\n"));
break;
case OPT_ANON:
if (done_anon++)
if (!val) {
}
/* check for special "-1" value, which is ok */
break;
case OPT_NOSUID:
if (done_nosuid++)
break;
case OPT_ACLOK:
if (done_aclok++)
break;
case OPT_NOSUB:
/*
* The "don't allow mount of subdirectories" option.
*/
break;
case OPT_PUBLIC:
break;
case OPT_INDEX:
break;
case OPT_LOG:
break;
#ifdef VOLATILE_FH_TEST /* XXX added for testing volatile fh's only */
case OPT_VOLFH:
/* volatile filehandles - expire on share */
break;
#endif /* VOLATILE_FH_TEST */
default:
}
}
/*
* Set uninitialized flags to "rw"
*/
for (i = 0; i < count; i++) {
}
}
/*
* check the argument specified with the index option and set
* export index file and flags
*/
static void
{
char *p = val;
goto badindexarg;
p = val;
while (*p != '\0') {
if (*p == '/')
goto badindexarg;
p++;
}
goto badindexarg;
/*
* treat a "." or an empty index string as if the
* index option is not present.
*/
return;
return;
}
return;
}
/*
* Given a seconfig entry and a colon-separated
* list of names, allocate an array big enough
* to hold the root list, then convert each name to
* a principal name according to the security
* info and assign it to an array element.
* Return the array and its size.
*/
static caddr_t *
{
caddr_t *a;
int c, i;
char *host, *p;
/*
* Count the number of strings in the list.
* This is the number of colon separators + 1.
*/
c = 1;
for (p = list; *p; p++)
if (*p == ':')
c++;
*count = c;
if (a == NULL)
for (i = 0; i < c; i++) {
a = NULL;
break;
}
}
return (a);
}
/*
* Append an entry to the sharetab file
*/
static int
int replace;
{
int ret;
FILE *f;
int logging = 0;
/*
* Open the file for update and create it if necessary.
* This may leave the I/O offset at the end of the file,
* so rewind back to the beginning of the file.
*/
if (f == NULL) {
return (-1);
}
rewind(f);
(void) fclose(f);
return (-1);
}
/*
* If re-sharing an old share with new options
* then first remove the old share entry.
*/
if (replace) {
switch (ret) {
case -1:
"failed to remove old sharetab"
" entry, no memory\n"));
break;
case -2:
"sharetab may be corrupt, ftrucate call"
" failure during sharetab update\n"));
break;
case -3:
"failed to remove old sharetab entry,"
" corrupt sharetab file\n"));
break;
}
}
if (logging) {
/*
* Entry replaced was logged, deactivate it in
* nfslogtab.
*/
(void) nfslogtab_deactivate(dir);
}
}
(void) fclose(f);
return (0);
}
/*
* Append an entry to the nfslogtab file
*/
static int
{
FILE *f;
struct logtab_ent lep;
int error = 0;
/*
* Open the file for update and create it if necessary.
* This may leave the I/O offset at the end of the file,
* so rewind back to the beginning of the file.
*/
if (f == NULL) {
"share complete, however failed to open %s "
goto out;
}
rewind(f);
"share complete, however failed to lock %s "
error = -1;
goto out;
}
if (logtab_deactivate_after_boot(f) == -1) {
"share complete, however could not deactivate "
"entries in %s\n"), NFSLOGTAB);
error = -1;
goto out;
}
/*
* Remove entries matching buffer and sharepoint since we're
* going to replace it with perhaps an entry with a new tag.
*/
"share complete, however could not remove matching "
"entries in %s\n"), NFSLOGTAB);
error = -1;
goto out;
}
/*
* Deactivate all active entries matching this sharepoint
*/
"share complete, however could not deactivate matching "
"entries in %s\n"), NFSLOGTAB);
error = -1;
goto out;
}
/*
* Add new sharepoint / buffer location to nfslogtab
*/
if (logtab_putent(f, &lep) < 0) {
"share complete, however could not add %s to %s\n"),
error = -1;
}
out:
if (f != NULL)
(void) fclose(f);
return (error);
}
/*
* Deactivate an entry from the nfslogtab file
*/
static int
char *path;
{
FILE *f;
int error = 0;
if (f == NULL) {
"share complete, however could not open %s for "
goto out;
}
"share complete, however could not lock %s for "
goto out;
}
error = -1;
goto out;
}
(void) fclose(f);
return (error);
}
static void
usage()
{
"Usage: share [-o options] [-d description] pathname [resource]\n");
}
/*
* This is for testing only
* It displays the export structure that
* goes into the kernel.
*/
static void
{
int i, j;
printf("NOSUID ");
printf("ACLOK ");
printf("PUBLIC ");
printf("NOSUB ");
printf("LOG ");
printf("LOG_ALLOPS ");
printf("(none)");
printf("\n");
printf("\tex_log_buffer = %s\n",
}
printf("\n");
printf("\n");
printf("\n\n");
}
}
/*
* Look for the specified tag in the configuration file. If it is found,
* enable logging and set the logging configuration information for exp.
*/
static void
{
int error = 0;
char globaltag[] = DEFAULTTAG;
/*
* Sends config errors to stderr
*/
/*
* get the list of configuration settings
*/
if (error) {
}
}
goto out;
}
goto out;
}
out:
if (error != 0) {
}
}
/*VARARGS1*/
static void
{
}