xref: /illumos-gate/usr/src/cmd/fs.d/nfs/mountd/nfs_cmd.c (revision 593cc11b0ce1691880b59ee5a8bd6adcdc823490)
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 2010 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/types.h>
28 #include <rpc/rpc.h>
29 #include <netconfig.h>
30 #include <netdir.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
33 #include <netdb.h>
34 #include <libtsnet.h>
35 #include <nfs/nfssys.h>
36 #include <nfs/export.h>
37 #include <nfs/nfs_cmd.h>
38 #include <door.h>
39 #include <syslog.h>
40 #include <locale.h>
41 #include <strings.h>
42 #include <sharefs/share.h>
43 
44 extern struct share *findentry(char *);
45 /*
46  * The following codesets must match what is in libshare_nfs.c until we can
47  * request them from the kernel.
48  */
49 char *charopts[] = {
50 	"euc-cn",
51 	"euc-jp",
52 	"euc-jpms",
53 	"euc-kr",
54 	"euc-tw",
55 	"iso8859-1",
56 	"iso8859-2",
57 	"iso8859-5",
58 	"iso8859-6",
59 	"iso8859-7",
60 	"iso8859-8",
61 	"iso8859-9",
62 	"iso8859-13",
63 	"iso8859-15",
64 	"koi8-r",
65 	NULL
66 };
67 
68 /*
69  * nfscmd_err(dp, args, err)
70  * Return an error for the door call.
71  */
72 
73 static void
74 nfscmd_err(door_desc_t *dp, nfscmd_arg_t *args, int err)
75 {
76 	nfscmd_res_t res;
77 
78 	res.version = NFSCMD_VERS_1;
79 	res.cmd = NFSCMD_ERROR;
80 	res.error = err;
81 	(void) door_return((char *)&res, sizeof (nfscmd_res_t), NULL, 0);
82 	(void) door_return(NULL, 0, NULL, 0);
83 	/* NOTREACHED */
84 
85 }
86 
87 /*
88  * charmap_search(netbuf, opts)
89  *
90  * Check to see if the address in the netbuf is found in
91  * a character map spec in the opts option string. Returns the charset
92  * name if found.
93  */
94 
95 static char *
96 charmap_search(struct netbuf *nbuf, char *opts)
97 {
98 	char *copts;
99 	char *next;
100 	char *name;
101 	char *result = NULL;
102 	char *netid;
103 	struct netconfig *nconf;
104 	struct nd_hostservlist  *hl = NULL;
105 	struct sockaddr *sa;
106 
107 	/* eventually charopts should be dynamically setup */
108 	if (charopts == NULL) {
109 		free(copts);
110 		return (NULL);
111 	}
112 
113 	sa = (struct sockaddr *)nbuf->buf;
114 
115 	switch (sa->sa_family) {
116 	case AF_INET:
117 		nconf = getnetconfigent("tcp");
118 		break;
119 	case AF_INET6:
120 		nconf = getnetconfigent("tcp6");
121 		break;
122 	default:
123 		return (NULL);
124 	}
125 
126 	if (nconf == NULL) {
127 		return (NULL);
128 	}
129 
130 	/*
131 	 * Use the this API instead of the netdir_getbyaddr()
132 	 * to avoid service lookup.
133 	 */
134 	if (__netdir_getbyaddr_nosrv(nconf, &hl, nbuf)) {
135 		syslog(LOG_ERR, "netdir: %s\n", netdir_sperror());
136 		freenetconfigent(nconf);
137 		return (NULL);
138 	}
139 
140 	copts = strdup(opts);
141 	if (copts == NULL) {
142 		freenetconfigent(nconf);
143 		return (NULL);
144 	}
145 
146 	next = copts;
147 	while (*next != '\0') {
148 		char *val;
149 		name = next;
150 		if (getsubopt(&next, charopts, &val) >= 0) {
151 			char *cp;
152 			/*
153 			 * name will have the whole opt and val the value. Set
154 			 * the '=' to '\0' and we have the charmap in name and
155 			 * the access list in val.
156 			 */
157 			cp = strchr(name, '=');
158 			if (cp != NULL)
159 				*cp = '\0';
160 			if (in_access_list(NULL, nbuf, &hl, val)) {
161 				result = name;
162 				break;
163 			}
164 		}
165 	}
166 
167 	if (result != NULL)
168 		result = strdup(result);
169 
170 	free(copts);
171 	freenetconfigent(nconf);
172 
173 	return (result);
174 }
175 
176 /*
177  * nfscmd_charmap_lookup(door, args)
178  *
179  * Check to see if there is a translation requested for the path
180  * specified in the request. If there is, return the charset name.
181  */
182 
183 static void
184 nfscmd_charmap_lookup(door_desc_t *dp, nfscmd_arg_t *args)
185 {
186 	nfscmd_res_t res;
187 	struct netbuf nb;
188 	struct sockaddr sa;
189 	struct share *sh = NULL;
190 	char *opts;
191 	char *name;
192 
193 	memset(&res, '\0', sizeof (res));
194 	res.version = NFSCMD_VERS_1;
195 	res.cmd = NFSCMD_CHARMAP_LOOKUP;
196 
197 	sh = findentry(args->arg.charmap.path);
198 
199 	if (sh != NULL) {
200 		nb.len = nb.maxlen = sizeof (struct sockaddr);
201 		nb.buf = (char *)&sa;
202 
203 		sa = args->arg.charmap.addr;
204 
205 		name = charmap_search(&nb, sh->sh_opts);
206 		if (name != NULL) {
207 			strcpy(res.result.charmap.codeset, name);
208 			res.result.charmap.apply = B_TRUE;
209 			res.error = NFSCMD_ERR_SUCCESS;
210 			free(name);
211 		} else {
212 			res.result.charmap.apply = B_FALSE;
213 			res.error = NFSCMD_ERR_NOTFOUND;
214 		}
215 		sharefree(sh);
216 	} else {
217 		res.error = NFSCMD_ERR_NOTFOUND;
218 	}
219 
220 	(void) door_return((char *)&res, sizeof (nfscmd_res_t), NULL, 0);
221 	(void) door_return(NULL, 0, NULL, 0);
222 	/* NOTREACHED */
223 }
224 
225 /*
226  * nfscmd_ver_1(door, args, size)
227  *
228  * Version 1 of the door command processor for nfs cmds.
229  */
230 
231 static void
232 nfscmd_vers_1(door_desc_t *dp, nfscmd_arg_t *args, size_t size)
233 {
234 	switch (args->cmd) {
235 	case NFSCMD_CHARMAP_LOOKUP:
236 		nfscmd_charmap_lookup(dp, args);
237 		break;
238 	default:
239 		nfscmd_err(dp, args, NFSCMD_ERR_BADCMD);
240 		break;
241 	}
242 }
243 
244 /*
245  * nfscmd_func(cookie, dataptr, size, door, ndesc)
246  *
247  * The function called by the door thread for processing
248  * nfscmd type commands.
249  */
250 
251 void
252 nfscmd_func(void *cookie, char *dataptr, size_t arg_size,
253 	door_desc_t *dp, uint_t n_desc)
254 {
255 	nfscmd_arg_t	*args;
256 
257 	args = (nfscmd_arg_t *)dataptr;
258 
259 	switch (args->version) {
260 	case NFSCMD_VERS_1:
261 		nfscmd_vers_1(dp, args, arg_size);
262 		break;
263 	default:
264 		syslog(LOG_ERR, gettext("Invalid nfscmd version"));
265 		break;
266 	}
267 
268 	(void) door_return((caddr_t)args, sizeof (nfscmd_res_t), NULL, 0);
269 	(void) door_return(NULL, 0, NULL, 0);
270 	/* NOTREACHED */
271 
272 }
273