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 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