1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * autod_autofs.c 24*0Sstevel@tonic-gate * 25*0Sstevel@tonic-gate * Copyright (c) 1988-1996 Sun Microsystems Inc 26*0Sstevel@tonic-gate * All Rights Reserved. 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include <stdio.h> 32*0Sstevel@tonic-gate #include <unistd.h> 33*0Sstevel@tonic-gate #include <stdlib.h> 34*0Sstevel@tonic-gate #include <ctype.h> 35*0Sstevel@tonic-gate #include <sys/param.h> 36*0Sstevel@tonic-gate #include <sys/stat.h> 37*0Sstevel@tonic-gate #include <sys/mntent.h> 38*0Sstevel@tonic-gate #include <sys/mnttab.h> 39*0Sstevel@tonic-gate #include <sys/mount.h> 40*0Sstevel@tonic-gate #include <sys/utsname.h> 41*0Sstevel@tonic-gate #include <sys/tiuser.h> 42*0Sstevel@tonic-gate #include <syslog.h> 43*0Sstevel@tonic-gate #include <string.h> 44*0Sstevel@tonic-gate #include <errno.h> 45*0Sstevel@tonic-gate #include <fslib.h> 46*0Sstevel@tonic-gate #include <sys/vfs.h> 47*0Sstevel@tonic-gate #include <assert.h> 48*0Sstevel@tonic-gate #include "automount.h" 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate static int process_opts(char *options, int *directp, int *sawnestp); 51*0Sstevel@tonic-gate void netbuf_free(struct netbuf *); 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate int 54*0Sstevel@tonic-gate mount_autofs( 55*0Sstevel@tonic-gate struct mapent *me, 56*0Sstevel@tonic-gate char *mntpnt, 57*0Sstevel@tonic-gate action_list *alp, 58*0Sstevel@tonic-gate char *rootp, 59*0Sstevel@tonic-gate char *subdir, 60*0Sstevel@tonic-gate char *key 61*0Sstevel@tonic-gate ) 62*0Sstevel@tonic-gate { 63*0Sstevel@tonic-gate int mntflags = 0; 64*0Sstevel@tonic-gate struct utsname utsname; 65*0Sstevel@tonic-gate struct autofs_args *fnip = NULL; 66*0Sstevel@tonic-gate int mount_timeout = AUTOFS_MOUNT_TIMEOUT; 67*0Sstevel@tonic-gate int sawnest, len, error = 0; 68*0Sstevel@tonic-gate char *buf, rel_mntpnt[MAXPATHLEN]; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate if (trace > 1) 71*0Sstevel@tonic-gate trace_prt(1, " mount_autofs %s on %s\n", 72*0Sstevel@tonic-gate me->map_fs->mfs_dir, mntpnt); 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate if (strcmp(mntpnt, "/-") == 0) { 75*0Sstevel@tonic-gate syslog(LOG_ERR, "invalid mountpoint: /-"); 76*0Sstevel@tonic-gate return (ENOENT); 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate /* 80*0Sstevel@tonic-gate * get relative mountpoint 81*0Sstevel@tonic-gate */ 82*0Sstevel@tonic-gate sprintf(rel_mntpnt, ".%s", mntpnt+strlen(rootp)); 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate if (trace > 2) 85*0Sstevel@tonic-gate trace_prt(1, "rel_mntpnt = %s\n", rel_mntpnt); 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate if (uname(&utsname) < 0) { 88*0Sstevel@tonic-gate error = errno; 89*0Sstevel@tonic-gate syslog(LOG_ERR, "uname %s", strerror(error)); 90*0Sstevel@tonic-gate return (error); 91*0Sstevel@tonic-gate } 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate if ((fnip = (struct autofs_args *) 94*0Sstevel@tonic-gate malloc(sizeof (struct autofs_args))) == NULL) { 95*0Sstevel@tonic-gate goto free_mem; 96*0Sstevel@tonic-gate } 97*0Sstevel@tonic-gate (void) memset((void *) fnip, 0, sizeof (*fnip)); 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate if ((fnip->addr.buf = (char *)malloc(MAXADDRLEN)) == NULL) 100*0Sstevel@tonic-gate goto free_mem; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate (void) strcpy(fnip->addr.buf, utsname.nodename); 103*0Sstevel@tonic-gate (void) strcat(fnip->addr.buf, ".autofs"); 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate if ((fnip->opts = malloc(MAX_MNTOPT_STR)) == NULL) 106*0Sstevel@tonic-gate goto free_mem; 107*0Sstevel@tonic-gate strcpy(fnip->opts, me->map_mntopts); 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate if (process_opts(fnip->opts, &fnip->direct, &sawnest) != 0) 110*0Sstevel@tonic-gate goto free_mem; 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate fnip->addr.len = strlen(fnip->addr.buf); 113*0Sstevel@tonic-gate fnip->addr.maxlen = fnip->addr.len; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate /* 116*0Sstevel@tonic-gate * get absolute mountpoint 117*0Sstevel@tonic-gate */ 118*0Sstevel@tonic-gate if ((fnip->path = strdup(mntpnt)) == NULL) 119*0Sstevel@tonic-gate goto free_mem; 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate if ((fnip->map = strdup(me->map_fs->mfs_dir)) == NULL) 122*0Sstevel@tonic-gate goto free_mem; 123*0Sstevel@tonic-gate if ((fnip->subdir = strdup(subdir)) == NULL) 124*0Sstevel@tonic-gate goto free_mem; 125*0Sstevel@tonic-gate /* 126*0Sstevel@tonic-gate * This timeout is really ignored by autofs, it uses the 127*0Sstevel@tonic-gate * parent directory's timeout since it's really the one 128*0Sstevel@tonic-gate * specified/inherited from the original mount by 'automount' 129*0Sstevel@tonic-gate */ 130*0Sstevel@tonic-gate fnip->mount_to = mount_timeout; /* IGNORED */ 131*0Sstevel@tonic-gate fnip->rpc_to = AUTOFS_RPC_TIMEOUT; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate if (fnip->direct) { 134*0Sstevel@tonic-gate if (me->map_modified == TRUE || me->map_faked == TRUE) { 135*0Sstevel@tonic-gate if ((fnip->key = strdup(key)) == NULL) 136*0Sstevel@tonic-gate goto free_mem; 137*0Sstevel@tonic-gate } else { 138*0Sstevel@tonic-gate /* wierd case of a direct map pointer in another map */ 139*0Sstevel@tonic-gate if ((fnip->key = strdup(fnip->path)) == NULL) 140*0Sstevel@tonic-gate goto free_mem; 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate } else { 143*0Sstevel@tonic-gate fnip->key = NULL; 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate /* 147*0Sstevel@tonic-gate * Fill out action list. 148*0Sstevel@tonic-gate */ 149*0Sstevel@tonic-gate alp->action.action = AUTOFS_MOUNT_RQ; 150*0Sstevel@tonic-gate if ((alp->action.action_list_entry_u.mounta.spec = 151*0Sstevel@tonic-gate strdup(me->map_fs->mfs_dir)) == NULL) 152*0Sstevel@tonic-gate goto free_mem; 153*0Sstevel@tonic-gate if ((alp->action.action_list_entry_u.mounta.dir = 154*0Sstevel@tonic-gate strdup(rel_mntpnt)) == NULL) 155*0Sstevel@tonic-gate goto free_mem; 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate len = strlen(fnip->opts); 158*0Sstevel@tonic-gate /* 159*0Sstevel@tonic-gate * Get a buffer for the option string, it holds the map options plus 160*0Sstevel@tonic-gate * space for "nest" if it isn't already in the option string 161*0Sstevel@tonic-gate */ 162*0Sstevel@tonic-gate if ((buf = (char *)malloc(MAX_MNTOPT_STR)) == NULL) 163*0Sstevel@tonic-gate goto free_mem; 164*0Sstevel@tonic-gate strcpy(buf, fnip->opts); 165*0Sstevel@tonic-gate if (!sawnest) { 166*0Sstevel@tonic-gate if (len + strlen(",nest") + 1 > MAX_MNTOPT_STR) 167*0Sstevel@tonic-gate goto free_mem; 168*0Sstevel@tonic-gate if (len) 169*0Sstevel@tonic-gate (void) strcat(buf, ","); 170*0Sstevel@tonic-gate (void) strcat(buf, "nest"); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.optptr = buf; 173*0Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.optlen = strlen(buf); 174*0Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.flags = 175*0Sstevel@tonic-gate mntflags | MS_DATA | MS_OPTIONSTR; 176*0Sstevel@tonic-gate if ((alp->action.action_list_entry_u.mounta.fstype = 177*0Sstevel@tonic-gate strdup(MNTTYPE_AUTOFS)) == NULL) 178*0Sstevel@tonic-gate goto free_mem; 179*0Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.dataptr = (char *)fnip; 180*0Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.datalen = sizeof (*fnip); 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate return (0); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate free_mem: 185*0Sstevel@tonic-gate /* 186*0Sstevel@tonic-gate * We got an error, free the memory we allocated. 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate syslog(LOG_ERR, "mount_autofs: memory allocation failure"); 189*0Sstevel@tonic-gate free_autofs_args(fnip); 190*0Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.dataptr = NULL; 191*0Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.datalen = 0; 192*0Sstevel@tonic-gate free_mounta(&alp->action.action_list_entry_u.mounta); 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate return (error ? error : ENOMEM); 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* 198*0Sstevel@tonic-gate * Set *directp to 1 if "direct" is found, and 0 otherwise 199*0Sstevel@tonic-gate * (mounts are indirect by default). If both "direct" and "indirect" are 200*0Sstevel@tonic-gate * found, the last one wins. 201*0Sstevel@tonic-gate * XXX - add nest to args if it's not there, this should go away later 202*0Sstevel@tonic-gate * when we add option string to the xdr data. 203*0Sstevel@tonic-gate */ 204*0Sstevel@tonic-gate static int 205*0Sstevel@tonic-gate process_opts(char *options, int *directp, int *sawnestp) 206*0Sstevel@tonic-gate { 207*0Sstevel@tonic-gate char *opt, *opts, *lasts; 208*0Sstevel@tonic-gate char buf[AUTOFS_MAXOPTSLEN]; 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate assert(strlen(options)+1 < AUTOFS_MAXOPTSLEN); 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate *sawnestp = 0; 213*0Sstevel@tonic-gate strcpy(buf, options); 214*0Sstevel@tonic-gate opts = buf; 215*0Sstevel@tonic-gate options[0] = '\0'; 216*0Sstevel@tonic-gate *directp = 0; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate while ((opt = strtok_r(opts, ",", &lasts)) != NULL) { 219*0Sstevel@tonic-gate opts = NULL; 220*0Sstevel@tonic-gate while (isspace(*opt)) { 221*0Sstevel@tonic-gate opt++; 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate if (strcmp(opt, "direct") == 0) { 224*0Sstevel@tonic-gate *directp = 1; 225*0Sstevel@tonic-gate } else if (strcmp(opt, "indirect") == 0) { 226*0Sstevel@tonic-gate *directp = 0; 227*0Sstevel@tonic-gate } else if (strcmp(opt, "ignore") != 0) { 228*0Sstevel@tonic-gate if (strcmp(opt, "nest") == 0) { 229*0Sstevel@tonic-gate *sawnestp = 1; 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate if (options[0] != '\0') { 232*0Sstevel@tonic-gate (void) strcat(options, ","); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate (void) strcat(options, opt); 235*0Sstevel@tonic-gate } 236*0Sstevel@tonic-gate }; 237*0Sstevel@tonic-gate return (0); 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate /* 241*0Sstevel@tonic-gate * Free autofs_args structure 242*0Sstevel@tonic-gate */ 243*0Sstevel@tonic-gate void 244*0Sstevel@tonic-gate free_autofs_args(struct autofs_args *p) 245*0Sstevel@tonic-gate { 246*0Sstevel@tonic-gate if (p == NULL) 247*0Sstevel@tonic-gate return; 248*0Sstevel@tonic-gate if (p->addr.buf) 249*0Sstevel@tonic-gate free(p->addr.buf); 250*0Sstevel@tonic-gate if (p->path) 251*0Sstevel@tonic-gate free(p->path); 252*0Sstevel@tonic-gate if (p->opts) 253*0Sstevel@tonic-gate free(p->opts); 254*0Sstevel@tonic-gate if (p->map) 255*0Sstevel@tonic-gate free(p->map); 256*0Sstevel@tonic-gate if (p->subdir) 257*0Sstevel@tonic-gate free(p->subdir); 258*0Sstevel@tonic-gate if (p->key) 259*0Sstevel@tonic-gate free(p->key); 260*0Sstevel@tonic-gate free(p); 261*0Sstevel@tonic-gate } 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate /* 264*0Sstevel@tonic-gate * free mounta structure. Assumes that m->dataptr has 265*0Sstevel@tonic-gate * been freed already 266*0Sstevel@tonic-gate */ 267*0Sstevel@tonic-gate void 268*0Sstevel@tonic-gate free_mounta(struct mounta *m) 269*0Sstevel@tonic-gate { 270*0Sstevel@tonic-gate if (m == NULL) 271*0Sstevel@tonic-gate return; 272*0Sstevel@tonic-gate if (m->spec) 273*0Sstevel@tonic-gate free(m->spec); 274*0Sstevel@tonic-gate if (m->dir) 275*0Sstevel@tonic-gate free(m->dir); 276*0Sstevel@tonic-gate if (m->fstype) 277*0Sstevel@tonic-gate free(m->fstype); 278*0Sstevel@tonic-gate if (m->optptr) 279*0Sstevel@tonic-gate free(m->optptr); 280*0Sstevel@tonic-gate assert(m->dataptr == NULL); 281*0Sstevel@tonic-gate assert(m->datalen == 0); 282*0Sstevel@tonic-gate /* 283*0Sstevel@tonic-gate * no need to free 'm' since it is part of the 284*0Sstevel@tonic-gate * action_list_entry structure. 285*0Sstevel@tonic-gate */ 286*0Sstevel@tonic-gate } 287