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