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