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