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