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