xref: /onnv-gate/usr/src/cmd/fs.d/nfs/mountd/exportlist.c (revision 3957:86c9dda5df37)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*3957Sth199096  * Common Development and Distribution License (the "License").
6*3957Sth199096  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*3957Sth199096 
220Sstevel@tonic-gate /*
23*3957Sth199096  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*3957Sth199096  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <stdio.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <syslog.h>
340Sstevel@tonic-gate #include <sys/param.h>
350Sstevel@tonic-gate #include <sys/stat.h>
360Sstevel@tonic-gate #include <sys/file.h>
370Sstevel@tonic-gate #include <sys/time.h>
380Sstevel@tonic-gate #include <errno.h>
390Sstevel@tonic-gate #include <rpcsvc/mount.h>
400Sstevel@tonic-gate #include <sys/pathconf.h>
410Sstevel@tonic-gate #include <sys/systeminfo.h>
420Sstevel@tonic-gate #include <sys/utsname.h>
430Sstevel@tonic-gate #include <signal.h>
440Sstevel@tonic-gate #include <locale.h>
450Sstevel@tonic-gate #include <unistd.h>
460Sstevel@tonic-gate #include <thread.h>
47*3957Sth199096 #include <sharefs/share.h>
48*3957Sth199096 #include <sharefs/sharetab.h>
490Sstevel@tonic-gate #include "../lib/sharetab.h"
500Sstevel@tonic-gate #include "mountd.h"
510Sstevel@tonic-gate 
520Sstevel@tonic-gate static void freeexports(struct exportnode *);
530Sstevel@tonic-gate static struct groupnode **newgroup(char *, struct groupnode **);
540Sstevel@tonic-gate static struct exportnode **newexport(char *, struct groupnode *,
550Sstevel@tonic-gate 						struct exportnode **);
560Sstevel@tonic-gate 
570Sstevel@tonic-gate static char *optlist[] = {
580Sstevel@tonic-gate #define	OPT_RO		0
590Sstevel@tonic-gate 	SHOPT_RO,
600Sstevel@tonic-gate #define	OPT_RW		1
610Sstevel@tonic-gate 	SHOPT_RW,
620Sstevel@tonic-gate 	NULL
630Sstevel@tonic-gate };
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  * Send current export list to a client
670Sstevel@tonic-gate  */
680Sstevel@tonic-gate void
export(struct svc_req * rqstp)690Sstevel@tonic-gate export(struct svc_req *rqstp)
700Sstevel@tonic-gate {
710Sstevel@tonic-gate 	SVCXPRT *transp;
720Sstevel@tonic-gate 	struct exportnode *exportlist;
730Sstevel@tonic-gate 	struct exportnode **tail;
740Sstevel@tonic-gate 	struct groupnode *groups;
750Sstevel@tonic-gate 	struct groupnode **grtail;
760Sstevel@tonic-gate 	struct share *sh;
770Sstevel@tonic-gate 	struct sh_list *shp;
780Sstevel@tonic-gate 	char *gr, *p, *opts, *val, *lasts;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	int export_to_everyone;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	transp = rqstp->rq_xprt;
830Sstevel@tonic-gate 	if (!svc_getargs(transp, xdr_void, NULL)) {
840Sstevel@tonic-gate 		svcerr_decode(transp);
850Sstevel@tonic-gate 		return;
860Sstevel@tonic-gate 	}
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 	check_sharetab();
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	exportlist = NULL;
910Sstevel@tonic-gate 	tail = &exportlist;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	(void) rw_rdlock(&sharetab_lock);
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	for (shp = share_list; shp; shp = shp->shl_next) {
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 		groups = NULL;
980Sstevel@tonic-gate 		grtail = &groups;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 		sh = shp->shl_sh;
1010Sstevel@tonic-gate 
1020Sstevel@tonic-gate 		/*
1030Sstevel@tonic-gate 		 * Check for "ro" or "rw" list without argument values.  This
1040Sstevel@tonic-gate 		 * indicates export to everyone.  Unfortunately, SunOS 4.x
1050Sstevel@tonic-gate 		 * automounter uses this, and it is indicated indirectly with
1060Sstevel@tonic-gate 		 * 'showmount -e'.
1070Sstevel@tonic-gate 		 *
1080Sstevel@tonic-gate 		 * If export_to_everyone is 1, then groups should be NULL to
1090Sstevel@tonic-gate 		 * indicate export to everyone.
1100Sstevel@tonic-gate 		 */
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 		opts = strdup(sh->sh_opts);
1130Sstevel@tonic-gate 		p = opts;
1140Sstevel@tonic-gate 
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 		export_to_everyone = 0;
1170Sstevel@tonic-gate 		while (*p) {
1180Sstevel@tonic-gate 			switch (getsubopt(&p, optlist, &val)) {
1190Sstevel@tonic-gate 			case OPT_RO:
1200Sstevel@tonic-gate 			case OPT_RW:
1210Sstevel@tonic-gate 				if (val == NULL)
1220Sstevel@tonic-gate 					export_to_everyone = 1;
1230Sstevel@tonic-gate 				break;
1240Sstevel@tonic-gate 			}
1250Sstevel@tonic-gate 		}
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 		free(opts);
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 		if (export_to_everyone == 0) {
1300Sstevel@tonic-gate 
1310Sstevel@tonic-gate 			opts = strdup(sh->sh_opts);
1320Sstevel@tonic-gate 			p = opts;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 			/*
1350Sstevel@tonic-gate 			 * Just concatenate all the hostnames/groups
1360Sstevel@tonic-gate 			 * from the "ro" and "rw" lists for each flavor.
1370Sstevel@tonic-gate 			 * This list is rather meaningless now, but
1380Sstevel@tonic-gate 			 * that's what the protocol demands.
1390Sstevel@tonic-gate 			 */
1400Sstevel@tonic-gate 			while (*p) {
1410Sstevel@tonic-gate 				switch (getsubopt(&p, optlist, &val)) {
1420Sstevel@tonic-gate 				case OPT_RO:
1430Sstevel@tonic-gate 				case OPT_RW:
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 					while ((gr = strtok_r(val, ":", &lasts))
1460Sstevel@tonic-gate 					    != NULL) {
1470Sstevel@tonic-gate 						val = NULL;
1480Sstevel@tonic-gate 						grtail = newgroup(gr, grtail);
1490Sstevel@tonic-gate 					}
1500Sstevel@tonic-gate 					break;
1510Sstevel@tonic-gate 				}
1520Sstevel@tonic-gate 			}
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 			free(opts);
1550Sstevel@tonic-gate 		}
1560Sstevel@tonic-gate 		tail = newexport(sh->sh_path, groups, tail);
1570Sstevel@tonic-gate 	}
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	(void) rw_unlock(&sharetab_lock);
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	errno = 0;
1620Sstevel@tonic-gate 	if (!svc_sendreply(transp, xdr_exports, (char *)&exportlist))
1630Sstevel@tonic-gate 		log_cant_reply(transp);
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 	freeexports(exportlist);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate static void
freeexports(struct exportnode * ex)1700Sstevel@tonic-gate freeexports(struct exportnode *ex)
1710Sstevel@tonic-gate {
1720Sstevel@tonic-gate 	struct groupnode *groups, *tmpgroups;
1730Sstevel@tonic-gate 	struct exportnode *tmpex;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	while (ex) {
1760Sstevel@tonic-gate 		groups = ex->ex_groups;
1770Sstevel@tonic-gate 		while (groups) {
1780Sstevel@tonic-gate 			tmpgroups = groups->gr_next;
1790Sstevel@tonic-gate 			free(groups->gr_name);
1800Sstevel@tonic-gate 			free(groups);
1810Sstevel@tonic-gate 			groups = tmpgroups;
1820Sstevel@tonic-gate 		}
1830Sstevel@tonic-gate 		tmpex = ex->ex_next;
1840Sstevel@tonic-gate 		free(ex->ex_dir);
1850Sstevel@tonic-gate 		free(ex);
1860Sstevel@tonic-gate 		ex = tmpex;
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate static struct groupnode **
newgroup(char * grname,struct groupnode ** tail)1920Sstevel@tonic-gate newgroup(char *grname, struct groupnode **tail)
1930Sstevel@tonic-gate {
1940Sstevel@tonic-gate 	struct groupnode *new;
1950Sstevel@tonic-gate 	char *newname;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	new = exmalloc(sizeof (*new));
1980Sstevel@tonic-gate 	newname = exmalloc(strlen(grname) + 1);
1990Sstevel@tonic-gate 	(void) strcpy(newname, grname);
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	new->gr_name = newname;
2020Sstevel@tonic-gate 	new->gr_next = NULL;
2030Sstevel@tonic-gate 	*tail = new;
2040Sstevel@tonic-gate 	return (&new->gr_next);
2050Sstevel@tonic-gate }
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate static struct exportnode **
newexport(char * grname,struct groupnode * grplist,struct exportnode ** tail)2090Sstevel@tonic-gate newexport(char *grname, struct groupnode *grplist, struct exportnode **tail)
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate 	struct exportnode *new;
2120Sstevel@tonic-gate 	char *newname;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	new = exmalloc(sizeof (*new));
2150Sstevel@tonic-gate 	newname = exmalloc(strlen(grname) + 1);
2160Sstevel@tonic-gate 	(void) strcpy(newname, grname);
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	new->ex_dir = newname;
2190Sstevel@tonic-gate 	new->ex_groups = grplist;
2200Sstevel@tonic-gate 	new->ex_next = NULL;
2210Sstevel@tonic-gate 	*tail = new;
2220Sstevel@tonic-gate 	return (&new->ex_next);
2230Sstevel@tonic-gate }
224