1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * nfs_subr.c 24*0Sstevel@tonic-gate * 25*0Sstevel@tonic-gate * Copyright (c) 1996 Sun Microsystems Inc 26*0Sstevel@tonic-gate * All Rights Reserved. 27*0Sstevel@tonic-gate */ 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate #include <stdlib.h> 32*0Sstevel@tonic-gate #include <string.h> 33*0Sstevel@tonic-gate #include <sys/types.h> 34*0Sstevel@tonic-gate #include <rpcsvc/nlm_prot.h> 35*0Sstevel@tonic-gate #include <sys/utsname.h> 36*0Sstevel@tonic-gate #include <nfs/nfs.h> 37*0Sstevel@tonic-gate #include "nfs_subr.h" 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate /* 40*0Sstevel@tonic-gate * This function is added to detect compatibility problem with SunOS4.x. 41*0Sstevel@tonic-gate * The compatibility problem exists when fshost cannot decode the request 42*0Sstevel@tonic-gate * arguments for NLM_GRANTED procedure. 43*0Sstevel@tonic-gate * Only in this case we use local locking. 44*0Sstevel@tonic-gate * In any other case we use fshost's lockd for remote file locking. 45*0Sstevel@tonic-gate * Return value: 1 if we should use local locking, 0 if not. 46*0Sstevel@tonic-gate */ 47*0Sstevel@tonic-gate int 48*0Sstevel@tonic-gate remote_lock(char *fshost, caddr_t fh) 49*0Sstevel@tonic-gate { 50*0Sstevel@tonic-gate nlm_testargs rlm_args; 51*0Sstevel@tonic-gate nlm_res rlm_res; 52*0Sstevel@tonic-gate struct timeval timeout = { 5, 0}; 53*0Sstevel@tonic-gate CLIENT *cl; 54*0Sstevel@tonic-gate enum clnt_stat rpc_stat; 55*0Sstevel@tonic-gate struct utsname myid; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate (void) memset((char *)&rlm_args, 0, sizeof (nlm_testargs)); 58*0Sstevel@tonic-gate (void) memset((char *)&rlm_res, 0, sizeof (nlm_res)); 59*0Sstevel@tonic-gate /* 60*0Sstevel@tonic-gate * Assign the hostname and the file handle for the 61*0Sstevel@tonic-gate * NLM_GRANTED request below. If for some reason the uname call fails, 62*0Sstevel@tonic-gate * list the server as the caller so that caller_name has some 63*0Sstevel@tonic-gate * reasonable value. 64*0Sstevel@tonic-gate */ 65*0Sstevel@tonic-gate if (uname(&myid) == -1) { 66*0Sstevel@tonic-gate rlm_args.alock.caller_name = fshost; 67*0Sstevel@tonic-gate } else { 68*0Sstevel@tonic-gate rlm_args.alock.caller_name = myid.nodename; 69*0Sstevel@tonic-gate } 70*0Sstevel@tonic-gate rlm_args.alock.fh.n_len = sizeof (fhandle_t); 71*0Sstevel@tonic-gate rlm_args.alock.fh.n_bytes = fh; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate cl = clnt_create(fshost, NLM_PROG, NLM_VERS, "datagram_v"); 74*0Sstevel@tonic-gate if (cl == NULL) 75*0Sstevel@tonic-gate return (0); 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate rpc_stat = clnt_call(cl, NLM_GRANTED, 78*0Sstevel@tonic-gate xdr_nlm_testargs, (caddr_t)&rlm_args, 79*0Sstevel@tonic-gate xdr_nlm_res, (caddr_t)&rlm_res, timeout); 80*0Sstevel@tonic-gate clnt_destroy(cl); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate return (rpc_stat == RPC_CANTDECODEARGS); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate #define fromhex(c) ((c >= '0' && c <= '9') ? (c - '0') : \ 86*0Sstevel@tonic-gate ((c >= 'A' && c <= 'F') ? (c - 'A' + 10) :\ 87*0Sstevel@tonic-gate ((c >= 'a' && c <= 'f') ? (c - 'a' + 10) : 0))) 88*0Sstevel@tonic-gate 89*0Sstevel@tonic-gate /* 90*0Sstevel@tonic-gate * The implementation of URLparse guarantees that the final string will 91*0Sstevel@tonic-gate * fit in the original one. Replaces '%' occurrences followed by 2 characters 92*0Sstevel@tonic-gate * with its corresponding hexadecimal character. 93*0Sstevel@tonic-gate */ 94*0Sstevel@tonic-gate void 95*0Sstevel@tonic-gate URLparse(char *str) 96*0Sstevel@tonic-gate { 97*0Sstevel@tonic-gate char *p, *q; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate p = q = str; 100*0Sstevel@tonic-gate while (*p) { 101*0Sstevel@tonic-gate *q = *p; 102*0Sstevel@tonic-gate if (*p++ == '%') { 103*0Sstevel@tonic-gate if (*p) { 104*0Sstevel@tonic-gate *q = fromhex(*p) * 16; 105*0Sstevel@tonic-gate p++; 106*0Sstevel@tonic-gate if (*p) { 107*0Sstevel@tonic-gate *q += fromhex(*p); 108*0Sstevel@tonic-gate p++; 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate } 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate q++; 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate *q = '\0'; 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate /* 118*0Sstevel@tonic-gate * Convert from URL syntax to host:path syntax. 119*0Sstevel@tonic-gate */ 120*0Sstevel@tonic-gate int 121*0Sstevel@tonic-gate convert_special(char **specialp, char *host, char *oldpath, char *newpath, 122*0Sstevel@tonic-gate char *cur_special) 123*0Sstevel@tonic-gate { 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate char *url; 126*0Sstevel@tonic-gate char *newspec; 127*0Sstevel@tonic-gate char *p; 128*0Sstevel@tonic-gate char *p1, *p2; 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate /* 131*0Sstevel@tonic-gate * Rebuild the URL. This is necessary because parse replica 132*0Sstevel@tonic-gate * assumes that nfs: is the host name. 133*0Sstevel@tonic-gate */ 134*0Sstevel@tonic-gate url = malloc(strlen("nfs:") + strlen(oldpath) + 1); 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate if (url == NULL) 137*0Sstevel@tonic-gate return (-1); 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate strcpy(url, "nfs:"); 140*0Sstevel@tonic-gate strcat(url, oldpath); 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* 143*0Sstevel@tonic-gate * If we haven't done any conversion yet, allocate a buffer for it. 144*0Sstevel@tonic-gate */ 145*0Sstevel@tonic-gate if (*specialp == NULL) { 146*0Sstevel@tonic-gate newspec = *specialp = strdup(cur_special); 147*0Sstevel@tonic-gate if (newspec == NULL) { 148*0Sstevel@tonic-gate free(url); 149*0Sstevel@tonic-gate return (-1); 150*0Sstevel@tonic-gate } 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate } else { 153*0Sstevel@tonic-gate newspec = *specialp; 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate /* 157*0Sstevel@tonic-gate * Now find the first occurence of the URL in the special string. 158*0Sstevel@tonic-gate */ 159*0Sstevel@tonic-gate p = strstr(newspec, url); 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate if (p == NULL) { 162*0Sstevel@tonic-gate free(url); 163*0Sstevel@tonic-gate return (-1); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate p1 = p; 167*0Sstevel@tonic-gate p2 = host; 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gate /* 170*0Sstevel@tonic-gate * Overwrite the URL in the special. 171*0Sstevel@tonic-gate * 172*0Sstevel@tonic-gate * Begin with the host name. 173*0Sstevel@tonic-gate */ 174*0Sstevel@tonic-gate for (;;) { 175*0Sstevel@tonic-gate /* 176*0Sstevel@tonic-gate * Sine URL's take more room than host:path, there is 177*0Sstevel@tonic-gate * no way we should hit a null byte in the original special. 178*0Sstevel@tonic-gate */ 179*0Sstevel@tonic-gate if (*p1 == '\0') { 180*0Sstevel@tonic-gate free(url); 181*0Sstevel@tonic-gate free(*specialp); 182*0Sstevel@tonic-gate *specialp = NULL; 183*0Sstevel@tonic-gate return (-1); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate if (*p2 == '\0') { 187*0Sstevel@tonic-gate break; 188*0Sstevel@tonic-gate } 189*0Sstevel@tonic-gate 190*0Sstevel@tonic-gate *p1 = *p2; 191*0Sstevel@tonic-gate p1++; 192*0Sstevel@tonic-gate p2++; 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate /* 196*0Sstevel@tonic-gate * Add the : separator. 197*0Sstevel@tonic-gate */ 198*0Sstevel@tonic-gate *p1 = ':'; 199*0Sstevel@tonic-gate p1++; 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate /* 202*0Sstevel@tonic-gate * Now over write into special the path portion of host:path in 203*0Sstevel@tonic-gate */ 204*0Sstevel@tonic-gate p2 = newpath; 205*0Sstevel@tonic-gate for (;;) { 206*0Sstevel@tonic-gate if (*p1 == '\0') { 207*0Sstevel@tonic-gate free(url); 208*0Sstevel@tonic-gate free(*specialp); 209*0Sstevel@tonic-gate *specialp = NULL; 210*0Sstevel@tonic-gate return (-1); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate if (*p2 == '\0') { 213*0Sstevel@tonic-gate break; 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate *p1 = *p2; 216*0Sstevel@tonic-gate p1++; 217*0Sstevel@tonic-gate p2++; 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate /* 221*0Sstevel@tonic-gate * Now shift the rest of original special into the gap created 222*0Sstevel@tonic-gate * by replacing nfs://host[:port]/path with host:path. 223*0Sstevel@tonic-gate */ 224*0Sstevel@tonic-gate p2 = p + strlen(url); 225*0Sstevel@tonic-gate for (;;) { 226*0Sstevel@tonic-gate if (*p1 == '\0') { 227*0Sstevel@tonic-gate free(url); 228*0Sstevel@tonic-gate free(*specialp); 229*0Sstevel@tonic-gate *specialp = NULL; 230*0Sstevel@tonic-gate return (-1); 231*0Sstevel@tonic-gate } 232*0Sstevel@tonic-gate if (*p2 == '\0') { 233*0Sstevel@tonic-gate break; 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate *p1 = *p2; 236*0Sstevel@tonic-gate p1++; 237*0Sstevel@tonic-gate p2++; 238*0Sstevel@tonic-gate } 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate *p1 = '\0'; 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate free(url); 243*0Sstevel@tonic-gate return (0); 244*0Sstevel@tonic-gate } 245