17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*39d3e169Sevanl * Common Development and Distribution License (the "License"). 6*39d3e169Sevanl * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * autod_autofs.c 237c478bd9Sstevel@tonic-gate * 24*39d3e169Sevanl * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25*39d3e169Sevanl * Use is subject to license terms. 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <unistd.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <ctype.h> 347c478bd9Sstevel@tonic-gate #include <sys/param.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 377c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 387c478bd9Sstevel@tonic-gate #include <sys/mount.h> 397c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 407c478bd9Sstevel@tonic-gate #include <sys/tiuser.h> 417c478bd9Sstevel@tonic-gate #include <syslog.h> 427c478bd9Sstevel@tonic-gate #include <string.h> 437c478bd9Sstevel@tonic-gate #include <errno.h> 447c478bd9Sstevel@tonic-gate #include <fslib.h> 457c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 467c478bd9Sstevel@tonic-gate #include <assert.h> 477c478bd9Sstevel@tonic-gate #include "automount.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate static int process_opts(char *options, int *directp, int *sawnestp); 507c478bd9Sstevel@tonic-gate void netbuf_free(struct netbuf *); 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate int 537c478bd9Sstevel@tonic-gate mount_autofs( 547c478bd9Sstevel@tonic-gate struct mapent *me, 557c478bd9Sstevel@tonic-gate char *mntpnt, 567c478bd9Sstevel@tonic-gate action_list *alp, 577c478bd9Sstevel@tonic-gate char *rootp, 587c478bd9Sstevel@tonic-gate char *subdir, 597c478bd9Sstevel@tonic-gate char *key 607c478bd9Sstevel@tonic-gate ) 617c478bd9Sstevel@tonic-gate { 627c478bd9Sstevel@tonic-gate int mntflags = 0; 637c478bd9Sstevel@tonic-gate struct utsname utsname; 64*39d3e169Sevanl autofs_args *fnip = NULL; 657c478bd9Sstevel@tonic-gate int mount_timeout = AUTOFS_MOUNT_TIMEOUT; 667c478bd9Sstevel@tonic-gate int sawnest, len, error = 0; 677c478bd9Sstevel@tonic-gate char *buf, rel_mntpnt[MAXPATHLEN]; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if (trace > 1) 707c478bd9Sstevel@tonic-gate trace_prt(1, " mount_autofs %s on %s\n", 717c478bd9Sstevel@tonic-gate me->map_fs->mfs_dir, mntpnt); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate if (strcmp(mntpnt, "/-") == 0) { 747c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "invalid mountpoint: /-"); 757c478bd9Sstevel@tonic-gate return (ENOENT); 767c478bd9Sstevel@tonic-gate } 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * get relative mountpoint 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate sprintf(rel_mntpnt, ".%s", mntpnt+strlen(rootp)); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate if (trace > 2) 847c478bd9Sstevel@tonic-gate trace_prt(1, "rel_mntpnt = %s\n", rel_mntpnt); 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate if (uname(&utsname) < 0) { 877c478bd9Sstevel@tonic-gate error = errno; 887c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "uname %s", strerror(error)); 897c478bd9Sstevel@tonic-gate return (error); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 92*39d3e169Sevanl if ((fnip = (autofs_args *) 93*39d3e169Sevanl malloc(sizeof (autofs_args))) == NULL) { 947c478bd9Sstevel@tonic-gate goto free_mem; 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate (void) memset((void *) fnip, 0, sizeof (*fnip)); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate if ((fnip->addr.buf = (char *)malloc(MAXADDRLEN)) == NULL) 997c478bd9Sstevel@tonic-gate goto free_mem; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate (void) strcpy(fnip->addr.buf, utsname.nodename); 1027c478bd9Sstevel@tonic-gate (void) strcat(fnip->addr.buf, ".autofs"); 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate if ((fnip->opts = malloc(MAX_MNTOPT_STR)) == NULL) 1057c478bd9Sstevel@tonic-gate goto free_mem; 1067c478bd9Sstevel@tonic-gate strcpy(fnip->opts, me->map_mntopts); 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate if (process_opts(fnip->opts, &fnip->direct, &sawnest) != 0) 1097c478bd9Sstevel@tonic-gate goto free_mem; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate fnip->addr.len = strlen(fnip->addr.buf); 1127c478bd9Sstevel@tonic-gate fnip->addr.maxlen = fnip->addr.len; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /* 1157c478bd9Sstevel@tonic-gate * get absolute mountpoint 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate if ((fnip->path = strdup(mntpnt)) == NULL) 1187c478bd9Sstevel@tonic-gate goto free_mem; 1197c478bd9Sstevel@tonic-gate if ((fnip->map = strdup(me->map_fs->mfs_dir)) == NULL) 1207c478bd9Sstevel@tonic-gate goto free_mem; 1217c478bd9Sstevel@tonic-gate if ((fnip->subdir = strdup(subdir)) == NULL) 1227c478bd9Sstevel@tonic-gate goto free_mem; 123*39d3e169Sevanl 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * This timeout is really ignored by autofs, it uses the 1267c478bd9Sstevel@tonic-gate * parent directory's timeout since it's really the one 1277c478bd9Sstevel@tonic-gate * specified/inherited from the original mount by 'automount' 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate fnip->mount_to = mount_timeout; /* IGNORED */ 1307c478bd9Sstevel@tonic-gate fnip->rpc_to = AUTOFS_RPC_TIMEOUT; 1317c478bd9Sstevel@tonic-gate 1327c478bd9Sstevel@tonic-gate if (fnip->direct) { 1337c478bd9Sstevel@tonic-gate if (me->map_modified == TRUE || me->map_faked == TRUE) { 1347c478bd9Sstevel@tonic-gate if ((fnip->key = strdup(key)) == NULL) 1357c478bd9Sstevel@tonic-gate goto free_mem; 1367c478bd9Sstevel@tonic-gate } else { 1377c478bd9Sstevel@tonic-gate /* wierd case of a direct map pointer in another map */ 1387c478bd9Sstevel@tonic-gate if ((fnip->key = strdup(fnip->path)) == NULL) 1397c478bd9Sstevel@tonic-gate goto free_mem; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate } else { 1427c478bd9Sstevel@tonic-gate fnip->key = NULL; 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * Fill out action list. 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate alp->action.action = AUTOFS_MOUNT_RQ; 1497c478bd9Sstevel@tonic-gate if ((alp->action.action_list_entry_u.mounta.spec = 1507c478bd9Sstevel@tonic-gate strdup(me->map_fs->mfs_dir)) == NULL) 1517c478bd9Sstevel@tonic-gate goto free_mem; 1527c478bd9Sstevel@tonic-gate if ((alp->action.action_list_entry_u.mounta.dir = 1537c478bd9Sstevel@tonic-gate strdup(rel_mntpnt)) == NULL) 1547c478bd9Sstevel@tonic-gate goto free_mem; 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate len = strlen(fnip->opts); 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Get a buffer for the option string, it holds the map options plus 1597c478bd9Sstevel@tonic-gate * space for "nest" if it isn't already in the option string 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate if ((buf = (char *)malloc(MAX_MNTOPT_STR)) == NULL) 1627c478bd9Sstevel@tonic-gate goto free_mem; 1637c478bd9Sstevel@tonic-gate strcpy(buf, fnip->opts); 1647c478bd9Sstevel@tonic-gate if (!sawnest) { 1657c478bd9Sstevel@tonic-gate if (len + strlen(",nest") + 1 > MAX_MNTOPT_STR) 1667c478bd9Sstevel@tonic-gate goto free_mem; 1677c478bd9Sstevel@tonic-gate if (len) 1687c478bd9Sstevel@tonic-gate (void) strcat(buf, ","); 1697c478bd9Sstevel@tonic-gate (void) strcat(buf, "nest"); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.optptr = buf; 172*39d3e169Sevanl alp->action.action_list_entry_u.mounta.optlen = strlen(buf) + 1; 1737c478bd9Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.flags = 1747c478bd9Sstevel@tonic-gate mntflags | MS_DATA | MS_OPTIONSTR; 1757c478bd9Sstevel@tonic-gate if ((alp->action.action_list_entry_u.mounta.fstype = 1767c478bd9Sstevel@tonic-gate strdup(MNTTYPE_AUTOFS)) == NULL) 1777c478bd9Sstevel@tonic-gate goto free_mem; 1787c478bd9Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.dataptr = (char *)fnip; 1797c478bd9Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.datalen = sizeof (*fnip); 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate return (0); 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate free_mem: 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * We got an error, free the memory we allocated. 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "mount_autofs: memory allocation failure"); 1887c478bd9Sstevel@tonic-gate free_autofs_args(fnip); 1897c478bd9Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.dataptr = NULL; 1907c478bd9Sstevel@tonic-gate alp->action.action_list_entry_u.mounta.datalen = 0; 1917c478bd9Sstevel@tonic-gate free_mounta(&alp->action.action_list_entry_u.mounta); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate return (error ? error : ENOMEM); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * Set *directp to 1 if "direct" is found, and 0 otherwise 1987c478bd9Sstevel@tonic-gate * (mounts are indirect by default). If both "direct" and "indirect" are 1997c478bd9Sstevel@tonic-gate * found, the last one wins. 2007c478bd9Sstevel@tonic-gate */ 2017c478bd9Sstevel@tonic-gate static int 2027c478bd9Sstevel@tonic-gate process_opts(char *options, int *directp, int *sawnestp) 2037c478bd9Sstevel@tonic-gate { 2047c478bd9Sstevel@tonic-gate char *opt, *opts, *lasts; 2057c478bd9Sstevel@tonic-gate char buf[AUTOFS_MAXOPTSLEN]; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate assert(strlen(options)+1 < AUTOFS_MAXOPTSLEN); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate *sawnestp = 0; 2107c478bd9Sstevel@tonic-gate strcpy(buf, options); 2117c478bd9Sstevel@tonic-gate opts = buf; 2127c478bd9Sstevel@tonic-gate options[0] = '\0'; 2137c478bd9Sstevel@tonic-gate *directp = 0; 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate while ((opt = strtok_r(opts, ",", &lasts)) != NULL) { 2167c478bd9Sstevel@tonic-gate opts = NULL; 2177c478bd9Sstevel@tonic-gate while (isspace(*opt)) { 2187c478bd9Sstevel@tonic-gate opt++; 2197c478bd9Sstevel@tonic-gate } 2207c478bd9Sstevel@tonic-gate if (strcmp(opt, "direct") == 0) { 2217c478bd9Sstevel@tonic-gate *directp = 1; 2227c478bd9Sstevel@tonic-gate } else if (strcmp(opt, "indirect") == 0) { 2237c478bd9Sstevel@tonic-gate *directp = 0; 2247c478bd9Sstevel@tonic-gate } else if (strcmp(opt, "ignore") != 0) { 2257c478bd9Sstevel@tonic-gate if (strcmp(opt, "nest") == 0) { 2267c478bd9Sstevel@tonic-gate *sawnestp = 1; 2277c478bd9Sstevel@tonic-gate } 2287c478bd9Sstevel@tonic-gate if (options[0] != '\0') { 2297c478bd9Sstevel@tonic-gate (void) strcat(options, ","); 2307c478bd9Sstevel@tonic-gate } 2317c478bd9Sstevel@tonic-gate (void) strcat(options, opt); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate }; 2347c478bd9Sstevel@tonic-gate return (0); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * Free autofs_args structure 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate void 241*39d3e169Sevanl free_autofs_args(autofs_args *p) 2427c478bd9Sstevel@tonic-gate { 2437c478bd9Sstevel@tonic-gate if (p == NULL) 2447c478bd9Sstevel@tonic-gate return; 2457c478bd9Sstevel@tonic-gate if (p->addr.buf) 2467c478bd9Sstevel@tonic-gate free(p->addr.buf); 2477c478bd9Sstevel@tonic-gate if (p->path) 2487c478bd9Sstevel@tonic-gate free(p->path); 2497c478bd9Sstevel@tonic-gate if (p->opts) 2507c478bd9Sstevel@tonic-gate free(p->opts); 2517c478bd9Sstevel@tonic-gate if (p->map) 2527c478bd9Sstevel@tonic-gate free(p->map); 2537c478bd9Sstevel@tonic-gate if (p->subdir) 2547c478bd9Sstevel@tonic-gate free(p->subdir); 2557c478bd9Sstevel@tonic-gate if (p->key) 2567c478bd9Sstevel@tonic-gate free(p->key); 2577c478bd9Sstevel@tonic-gate free(p); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* 2617c478bd9Sstevel@tonic-gate * free mounta structure. Assumes that m->dataptr has 2627c478bd9Sstevel@tonic-gate * been freed already 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate void 2657c478bd9Sstevel@tonic-gate free_mounta(struct mounta *m) 2667c478bd9Sstevel@tonic-gate { 2677c478bd9Sstevel@tonic-gate if (m == NULL) 2687c478bd9Sstevel@tonic-gate return; 2697c478bd9Sstevel@tonic-gate if (m->spec) 2707c478bd9Sstevel@tonic-gate free(m->spec); 2717c478bd9Sstevel@tonic-gate if (m->dir) 2727c478bd9Sstevel@tonic-gate free(m->dir); 2737c478bd9Sstevel@tonic-gate if (m->fstype) 2747c478bd9Sstevel@tonic-gate free(m->fstype); 2757c478bd9Sstevel@tonic-gate if (m->optptr) 2767c478bd9Sstevel@tonic-gate free(m->optptr); 2777c478bd9Sstevel@tonic-gate assert(m->dataptr == NULL); 2787c478bd9Sstevel@tonic-gate assert(m->datalen == 0); 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * no need to free 'm' since it is part of the 2817c478bd9Sstevel@tonic-gate * action_list_entry structure. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate } 284