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 #include <stdlib.h> 27 #include <string.h> 28 #include <sys/types.h> 29 #include <rpcsvc/nlm_prot.h> 30 #include <sys/utsname.h> 31 #include <nfs/nfs.h> 32 #include "nfs_subr.h" 33 #include <errno.h> 34 #include <deflt.h> 35 #include <rpcsvc/daemon_utils.h> 36 #include "smfcfg.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 #define AUTOFS_MOUNT_TIMEOUT 600 /* default min time mount will */ 249 250 void 251 set_nfsv4_ephemeral_mount_to(void) 252 { 253 char valbuf[6]; 254 int bufsz = sizeof (valbuf); 255 256 uint_t mount_to = AUTOFS_MOUNT_TIMEOUT; 257 258 /* 259 * Get the value from SMF 260 */ 261 if (autofs_smf_get_prop("timeout", valbuf, DEFAULT_INSTANCE, 262 SCF_TYPE_INTEGER, AUTOMOUNTD, &bufsz) == SA_OK) { 263 const char *errstr; 264 uint_t val = strtonum(valbuf, 0, UINT_MAX, &errstr); 265 if (errstr == NULL) 266 mount_to = val; 267 } 268 269 (void) _nfssys(NFS4_EPHEMERAL_MOUNT_TO, &mount_to); 270 } 271