xref: /illumos-gate/usr/src/cmd/fs.d/nfs/mountd/nfs_cmd.c (revision 544783ca)
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
nfscmd_err(door_desc_t * dp,nfscmd_arg_t * args,int err)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 *
charmap_search(struct netbuf * nbuf,char * opts)98 charmap_search(struct netbuf *nbuf, char *opts)
99 {
100 	char *copts;
101 	char *next;
102 	char *name;
103 	char *result = NULL;
104 	char *netid;
105 	struct sockaddr *sa;
106 
107 	struct cln cln;
108 
109 	sa = (struct sockaddr *)nbuf->buf;
110 
111 	switch (sa->sa_family) {
112 	case AF_INET:
113 		netid = "tcp";
114 		break;
115 	case AF_INET6:
116 		netid = "tcp6";
117 		break;
118 	default:
119 		return (NULL);
120 	}
121 
122 	copts = strdup(opts);
123 	if (copts == NULL)
124 		return (NULL);
125 
126 	cln_init_lazy(&cln, netid, nbuf);
127 
128 	next = copts;
129 	while (*next != '\0') {
130 		char *val;
131 		name = next;
132 		if (getsubopt(&next, charopts, &val) >= 0) {
133 			char *cp;
134 			/*
135 			 * name will have the whole opt and val the value. Set
136 			 * the '=' to '\0' and we have the charmap in name and
137 			 * the access list in val.
138 			 */
139 			cp = strchr(name, '=');
140 			if (cp != NULL)
141 				*cp = '\0';
142 			if (in_access_list(&cln, val) > 0) {
143 				result = name;
144 				break;
145 			}
146 		}
147 	}
148 
149 	if (result != NULL)
150 		result = strdup(result);
151 
152 	cln_fini(&cln);
153 	free(copts);
154 
155 	return (result);
156 }
157 
158 /*
159  * nfscmd_charmap_lookup(door, args)
160  *
161  * Check to see if there is a translation requested for the path
162  * specified in the request. If there is, return the charset name.
163  */
164 
165 static void
nfscmd_charmap_lookup(door_desc_t * dp,nfscmd_arg_t * args)166 nfscmd_charmap_lookup(door_desc_t *dp, nfscmd_arg_t *args)
167 {
168 	nfscmd_res_t res;
169 	struct netbuf nb;
170 	struct sockaddr sa;
171 	struct share *sh = NULL;
172 	char *name;
173 
174 	memset(&res, '\0', sizeof (res));
175 	res.version = NFSCMD_VERS_1;
176 	res.cmd = NFSCMD_CHARMAP_LOOKUP;
177 
178 	sh = findentry(args->arg.charmap.path);
179 
180 	if (sh != NULL) {
181 		nb.len = nb.maxlen = sizeof (struct sockaddr);
182 		nb.buf = (char *)&sa;
183 
184 		sa = args->arg.charmap.addr;
185 
186 		name = charmap_search(&nb, sh->sh_opts);
187 		if (name != NULL) {
188 			(void) strcpy(res.result.charmap.codeset, name);
189 			res.result.charmap.apply = B_TRUE;
190 			res.error = NFSCMD_ERR_SUCCESS;
191 			free(name);
192 		} else {
193 			res.result.charmap.apply = B_FALSE;
194 			res.error = NFSCMD_ERR_NOTFOUND;
195 		}
196 		sharefree(sh);
197 	} else {
198 		res.error = NFSCMD_ERR_NOTFOUND;
199 	}
200 
201 	(void) door_return((char *)&res, sizeof (nfscmd_res_t), NULL, 0);
202 	(void) door_return(NULL, 0, NULL, 0);
203 	/* NOTREACHED */
204 }
205 
206 /*
207  * nfscmd_ver_1(door, args, size)
208  *
209  * Version 1 of the door command processor for nfs cmds.
210  */
211 
212 static void
nfscmd_vers_1(door_desc_t * dp,nfscmd_arg_t * args,size_t size)213 nfscmd_vers_1(door_desc_t *dp, nfscmd_arg_t *args, size_t size)
214 {
215 	switch (args->cmd) {
216 	case NFSCMD_CHARMAP_LOOKUP:
217 		nfscmd_charmap_lookup(dp, args);
218 		break;
219 	default:
220 		nfscmd_err(dp, args, NFSCMD_ERR_BADCMD);
221 		break;
222 	}
223 }
224 
225 /*
226  * nfscmd_func(cookie, dataptr, size, door, ndesc)
227  *
228  * The function called by the door thread for processing
229  * nfscmd type commands.
230  */
231 
232 void
nfscmd_func(void * cookie,char * dataptr,size_t arg_size,door_desc_t * dp,uint_t n_desc)233 nfscmd_func(void *cookie, char *dataptr, size_t arg_size,
234     door_desc_t *dp, uint_t n_desc)
235 {
236 	nfscmd_arg_t	*args;
237 
238 	args = (nfscmd_arg_t *)dataptr;
239 
240 	switch (args->version) {
241 	case NFSCMD_VERS_1:
242 		nfscmd_vers_1(dp, args, arg_size);
243 		break;
244 	default:
245 		syslog(LOG_ERR, gettext("Invalid nfscmd version"));
246 		break;
247 	}
248 
249 	(void) door_return((caddr_t)args, sizeof (nfscmd_res_t), NULL, 0);
250 	(void) door_return(NULL, 0, NULL, 0);
251 	/* NOTREACHED */
252 
253 }
254