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