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