1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <sys/types.h> 32 #include <string.h> 33 #include <syslog.h> 34 #include <sys/param.h> 35 #include <sys/stat.h> 36 #include <sys/file.h> 37 #include <sys/time.h> 38 #include <errno.h> 39 #include <rpcsvc/mount.h> 40 #include <sys/pathconf.h> 41 #include <sys/systeminfo.h> 42 #include <sys/utsname.h> 43 #include <signal.h> 44 #include <locale.h> 45 #include <unistd.h> 46 #include <thread.h> 47 #include <sharefs/share.h> 48 #include <sharefs/sharetab.h> 49 #include "../lib/sharetab.h" 50 #include "mountd.h" 51 52 static void freeexports(struct exportnode *); 53 static struct groupnode **newgroup(char *, struct groupnode **); 54 static struct exportnode **newexport(char *, struct groupnode *, 55 struct exportnode **); 56 57 static char *optlist[] = { 58 #define OPT_RO 0 59 SHOPT_RO, 60 #define OPT_RW 1 61 SHOPT_RW, 62 NULL 63 }; 64 65 /* 66 * Send current export list to a client 67 */ 68 void 69 export(struct svc_req *rqstp) 70 { 71 SVCXPRT *transp; 72 struct exportnode *exportlist; 73 struct exportnode **tail; 74 struct groupnode *groups; 75 struct groupnode **grtail; 76 struct share *sh; 77 struct sh_list *shp; 78 char *gr, *p, *opts, *val, *lasts; 79 80 int export_to_everyone; 81 82 transp = rqstp->rq_xprt; 83 if (!svc_getargs(transp, xdr_void, NULL)) { 84 svcerr_decode(transp); 85 return; 86 } 87 88 check_sharetab(); 89 90 exportlist = NULL; 91 tail = &exportlist; 92 93 (void) rw_rdlock(&sharetab_lock); 94 95 for (shp = share_list; shp; shp = shp->shl_next) { 96 97 groups = NULL; 98 grtail = &groups; 99 100 sh = shp->shl_sh; 101 102 /* 103 * Check for "ro" or "rw" list without argument values. This 104 * indicates export to everyone. Unfortunately, SunOS 4.x 105 * automounter uses this, and it is indicated indirectly with 106 * 'showmount -e'. 107 * 108 * If export_to_everyone is 1, then groups should be NULL to 109 * indicate export to everyone. 110 */ 111 112 opts = strdup(sh->sh_opts); 113 p = opts; 114 115 116 export_to_everyone = 0; 117 while (*p) { 118 switch (getsubopt(&p, optlist, &val)) { 119 case OPT_RO: 120 case OPT_RW: 121 if (val == NULL) 122 export_to_everyone = 1; 123 break; 124 } 125 } 126 127 free(opts); 128 129 if (export_to_everyone == 0) { 130 131 opts = strdup(sh->sh_opts); 132 p = opts; 133 134 /* 135 * Just concatenate all the hostnames/groups 136 * from the "ro" and "rw" lists for each flavor. 137 * This list is rather meaningless now, but 138 * that's what the protocol demands. 139 */ 140 while (*p) { 141 switch (getsubopt(&p, optlist, &val)) { 142 case OPT_RO: 143 case OPT_RW: 144 145 while ((gr = strtok_r(val, ":", &lasts)) 146 != NULL) { 147 val = NULL; 148 grtail = newgroup(gr, grtail); 149 } 150 break; 151 } 152 } 153 154 free(opts); 155 } 156 tail = newexport(sh->sh_path, groups, tail); 157 } 158 159 (void) rw_unlock(&sharetab_lock); 160 161 errno = 0; 162 if (!svc_sendreply(transp, xdr_exports, (char *)&exportlist)) 163 log_cant_reply(transp); 164 165 freeexports(exportlist); 166 } 167 168 169 static void 170 freeexports(struct exportnode *ex) 171 { 172 struct groupnode *groups, *tmpgroups; 173 struct exportnode *tmpex; 174 175 while (ex) { 176 groups = ex->ex_groups; 177 while (groups) { 178 tmpgroups = groups->gr_next; 179 free(groups->gr_name); 180 free(groups); 181 groups = tmpgroups; 182 } 183 tmpex = ex->ex_next; 184 free(ex->ex_dir); 185 free(ex); 186 ex = tmpex; 187 } 188 } 189 190 191 static struct groupnode ** 192 newgroup(char *grname, struct groupnode **tail) 193 { 194 struct groupnode *new; 195 char *newname; 196 197 new = exmalloc(sizeof (*new)); 198 newname = exmalloc(strlen(grname) + 1); 199 (void) strcpy(newname, grname); 200 201 new->gr_name = newname; 202 new->gr_next = NULL; 203 *tail = new; 204 return (&new->gr_next); 205 } 206 207 208 static struct exportnode ** 209 newexport(char *grname, struct groupnode *grplist, struct exportnode **tail) 210 { 211 struct exportnode *new; 212 char *newname; 213 214 new = exmalloc(sizeof (*new)); 215 newname = exmalloc(strlen(grname) + 1); 216 (void) strcpy(newname, grname); 217 218 new->ex_dir = newname; 219 new->ex_groups = grplist; 220 new->ex_next = NULL; 221 *tail = new; 222 return (&new->ex_next); 223 } 224