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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdlib.h> 29 #include <string.h> 30 #include <sys/types.h> 31 #include <rpcsvc/nlm_prot.h> 32 #include <sys/utsname.h> 33 #include <nfs/nfs.h> 34 #include "nfs_subr.h" 35 #include <errno.h> 36 #include <deflt.h> 37 38 #include <nfs/nfssys.h> 39 extern int _nfssys(enum nfssys_op, void *); 40 41 /* 42 * This function is added to detect compatibility problem with SunOS4.x. 43 * The compatibility problem exists when fshost cannot decode the request 44 * arguments for NLM_GRANTED procedure. 45 * Only in this case we use local locking. 46 * In any other case we use fshost's lockd for remote file locking. 47 * Return value: 1 if we should use local locking, 0 if not. 48 */ 49 int 50 remote_lock(char *fshost, caddr_t fh) 51 { 52 nlm_testargs rlm_args; 53 nlm_res rlm_res; 54 struct timeval timeout = { 5, 0}; 55 CLIENT *cl; 56 enum clnt_stat rpc_stat; 57 struct utsname myid; 58 59 (void) memset((char *)&rlm_args, 0, sizeof (nlm_testargs)); 60 (void) memset((char *)&rlm_res, 0, sizeof (nlm_res)); 61 /* 62 * Assign the hostname and the file handle for the 63 * NLM_GRANTED request below. If for some reason the uname call fails, 64 * list the server as the caller so that caller_name has some 65 * reasonable value. 66 */ 67 if (uname(&myid) == -1) { 68 rlm_args.alock.caller_name = fshost; 69 } else { 70 rlm_args.alock.caller_name = myid.nodename; 71 } 72 rlm_args.alock.fh.n_len = sizeof (fhandle_t); 73 rlm_args.alock.fh.n_bytes = fh; 74 75 cl = clnt_create(fshost, NLM_PROG, NLM_VERS, "datagram_v"); 76 if (cl == NULL) 77 return (0); 78 79 rpc_stat = clnt_call(cl, NLM_GRANTED, 80 xdr_nlm_testargs, (caddr_t)&rlm_args, 81 xdr_nlm_res, (caddr_t)&rlm_res, timeout); 82 clnt_destroy(cl); 83 84 return (rpc_stat == RPC_CANTDECODEARGS); 85 } 86 87 #define fromhex(c) ((c >= '0' && c <= '9') ? (c - '0') : \ 88 ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) :\ 89 ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : 0))) 90 91 /* 92 * The implementation of URLparse guarantees that the final string will 93 * fit in the original one. Replaces '%' occurrences followed by 2 characters 94 * with its corresponding hexadecimal character. 95 */ 96 void 97 URLparse(char *str) 98 { 99 char *p, *q; 100 101 p = q = str; 102 while (*p) { 103 *q = *p; 104 if (*p++ == '%') { 105 if (*p) { 106 *q = fromhex(*p) * 16; 107 p++; 108 if (*p) { 109 *q += fromhex(*p); 110 p++; 111 } 112 } 113 } 114 q++; 115 } 116 *q = '\0'; 117 } 118 119 /* 120 * Convert from URL syntax to host:path syntax. 121 */ 122 int 123 convert_special(char **specialp, char *host, char *oldpath, char *newpath, 124 char *cur_special) 125 { 126 127 char *url; 128 char *newspec; 129 char *p; 130 char *p1, *p2; 131 132 /* 133 * Rebuild the URL. This is necessary because parse replica 134 * assumes that nfs: is the host name. 135 */ 136 url = malloc(strlen("nfs:") + strlen(oldpath) + 1); 137 138 if (url == NULL) 139 return (-1); 140 141 strcpy(url, "nfs:"); 142 strcat(url, oldpath); 143 144 /* 145 * If we haven't done any conversion yet, allocate a buffer for it. 146 */ 147 if (*specialp == NULL) { 148 newspec = *specialp = strdup(cur_special); 149 if (newspec == NULL) { 150 free(url); 151 return (-1); 152 } 153 154 } else { 155 newspec = *specialp; 156 } 157 158 /* 159 * Now find the first occurence of the URL in the special string. 160 */ 161 p = strstr(newspec, url); 162 163 if (p == NULL) { 164 free(url); 165 return (-1); 166 } 167 168 p1 = p; 169 p2 = host; 170 171 /* 172 * Overwrite the URL in the special. 173 * 174 * Begin with the host name. 175 */ 176 for (;;) { 177 /* 178 * Sine URL's take more room than host:path, there is 179 * no way we should hit a null byte in the original special. 180 */ 181 if (*p1 == '\0') { 182 free(url); 183 free(*specialp); 184 *specialp = NULL; 185 return (-1); 186 } 187 188 if (*p2 == '\0') { 189 break; 190 } 191 192 *p1 = *p2; 193 p1++; 194 p2++; 195 } 196 197 /* 198 * Add the : separator. 199 */ 200 *p1 = ':'; 201 p1++; 202 203 /* 204 * Now over write into special the path portion of host:path in 205 */ 206 p2 = newpath; 207 for (;;) { 208 if (*p1 == '\0') { 209 free(url); 210 free(*specialp); 211 *specialp = NULL; 212 return (-1); 213 } 214 if (*p2 == '\0') { 215 break; 216 } 217 *p1 = *p2; 218 p1++; 219 p2++; 220 } 221 222 /* 223 * Now shift the rest of original special into the gap created 224 * by replacing nfs://host[:port]/path with host:path. 225 */ 226 p2 = p + strlen(url); 227 for (;;) { 228 if (*p1 == '\0') { 229 free(url); 230 free(*specialp); 231 *specialp = NULL; 232 return (-1); 233 } 234 if (*p2 == '\0') { 235 break; 236 } 237 *p1 = *p2; 238 p1++; 239 p2++; 240 } 241 242 *p1 = '\0'; 243 244 free(url); 245 return (0); 246 } 247 248 /* 249 * Solaris autofs configuration file location 250 */ 251 #define AUTOFSADMIN "/etc/default/autofs" 252 #define AUTOFS_MOUNT_TIMEOUT 600 /* default min time mount will */ 253 254 void 255 set_nfsv4_ephemeral_mount_to(void) 256 { 257 char *defval; 258 259 uint_t mount_to = AUTOFS_MOUNT_TIMEOUT; 260 261 /* 262 * Get the value from /etc/default/autofs 263 */ 264 if ((defopen(AUTOFSADMIN)) == 0) { 265 if ((defval = defread("AUTOMOUNT_TIMEOUT=")) != NULL) { 266 errno = 0; 267 mount_to = strtoul(defval, (char **)NULL, 10); 268 if (errno != 0) 269 mount_to = AUTOFS_MOUNT_TIMEOUT; 270 } 271 272 /* close defaults file */ 273 defopen(NULL); 274 } 275 276 (void) _nfssys(NFS4_EPHEMERAL_MOUNT_TO, &mount_to); 277 } 278