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  *	autod_lookup.c
23  *
24  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <errno.h>
33 #include <locale.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <assert.h>
37 #include "automount.h"
38 
39 int
do_lookup1(char * mapname,char * key,char * subdir,char * mapopts,char * path,uint_t isdirect,uid_t uid,autofs_action_t * action,struct linka * linkp)40 do_lookup1(
41 	char *mapname,
42 	char *key,
43 	char *subdir,
44 	char *mapopts,
45 	char *path,
46 	uint_t isdirect,
47 	uid_t uid,
48 	autofs_action_t *action,
49 	struct linka *linkp)
50 {
51 	struct mapline ml;
52 	struct mapent *mapents = NULL;
53 	int err;
54 	struct autofs_rddir_cache *rdcp;
55 	int found = 0;
56 	bool_t iswildcard = FALSE;
57 	bool_t isrestricted = hasrestrictopt(mapopts);
58 	char *stack[STACKSIZ];
59 	char **stkptr = stack;
60 
61 	/*
62 	 * Default action is for no work to be done by kernel AUTOFS.
63 	 */
64 	*action = AUTOFS_NONE;
65 
66 	/*
67 	 * Is there a cache for this map?
68 	 */
69 	rw_rdlock(&autofs_rddir_cache_lock);
70 	err = autofs_rddir_cache_lookup(mapname, &rdcp);
71 	if (!err && rdcp->full) {
72 		rw_unlock(&autofs_rddir_cache_lock);
73 		/*
74 		 * Try to lock readdir cache entry for reading, if
75 		 * the entry can not be locked, then avoid blocking
76 		 * and go to the name service. I'm assuming it is
77 		 * faster to go to the name service than to wait for
78 		 * the cache to be populated.
79 		 */
80 		if (rw_tryrdlock(&rdcp->rwlock) == 0) {
81 			found = (rddir_entry_lookup(key, rdcp->entp) != NULL);
82 			rw_unlock(&rdcp->rwlock);
83 		}
84 	} else
85 		rw_unlock(&autofs_rddir_cache_lock);
86 
87 	if (!err) {
88 		/*
89 		 * release reference on cache entry
90 		 */
91 		mutex_lock(&rdcp->lock);
92 		rdcp->in_use--;
93 		assert(rdcp->in_use >= 0);
94 		mutex_unlock(&rdcp->lock);
95 	}
96 
97 	if (found)
98 		return (0);
99 
100 	/*
101 	 * entry not found in cache, try the name service now
102 	 */
103 	err = 0;
104 
105 	/* initialize the stack of open files for this thread */
106 	stack_op(INIT, NULL, stack, &stkptr);
107 
108 	err = getmapent(key, mapname, &ml, stack, &stkptr, &iswildcard,
109 		isrestricted);
110 	if (err == 0) /* call parser w default mount_access = TRUE */
111 		mapents = parse_entry(key, mapname, mapopts, &ml,
112 				    subdir, isdirect, TRUE);
113 
114 	/*
115 	 * Now we indulge in a bit of hanky-panky.
116 	 * If the entry isn't found in the map and the
117 	 * name begins with an "=" then we assume that
118 	 * the name is an undocumented control message
119 	 * for the daemon.  This is accessible only
120 	 * to superusers.
121 	 */
122 	if (mapents == NULL && *action == AUTOFS_NONE) {
123 		if (*key == '=' && uid == 0) {
124 			if (isdigit(*(key+1))) {
125 				/*
126 				 * If next character is a digit
127 				 * then set the trace level.
128 				 */
129 				trace = atoi(key+1);
130 				trace_prt(1, "Automountd: trace level = %d\n",
131 					trace);
132 			} else if (*(key+1) == 'v') {
133 				/*
134 				 * If it's a "v" then
135 				 * toggle verbose mode.
136 				 */
137 				verbose = !verbose;
138 				trace_prt(1, "Automountd: verbose %s\n",
139 						verbose ? "on" : "off");
140 			}
141 		}
142 
143 		err = ENOENT;
144 		goto done;
145 	}
146 
147 	/*
148 	 * Each mapent in the list describes a mount to be done.
149 	 * Since I'm only doing a lookup, I only care whether a mapentry
150 	 * was found or not. The mount will be done on a later RPC to
151 	 * do_mount1.
152 	 */
153 	if (mapents == NULL && *action == AUTOFS_NONE)
154 		err = ENOENT;
155 
156 done:	if (mapents)
157 		free_mapent(mapents);
158 
159 	if (*action == AUTOFS_NONE && (iswildcard == TRUE)) {
160 		*action = AUTOFS_MOUNT_RQ;
161 	}
162 	if (trace > 1) {
163 		trace_prt(1, "  do_lookup1: action=%d wildcard=%s error=%d\n",
164 			*action, iswildcard ? "TRUE" : "FALSE", err);
165 	}
166 	return (err);
167 }
168