1*2f172c55SRobert Thurlow /* 2*2f172c55SRobert Thurlow * CDDL HEADER START 3*2f172c55SRobert Thurlow * 4*2f172c55SRobert Thurlow * The contents of this file are subject to the terms of the 5*2f172c55SRobert Thurlow * Common Development and Distribution License (the "License"). 6*2f172c55SRobert Thurlow * You may not use this file except in compliance with the License. 7*2f172c55SRobert Thurlow * 8*2f172c55SRobert Thurlow * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2f172c55SRobert Thurlow * or http://www.opensolaris.org/os/licensing. 10*2f172c55SRobert Thurlow * See the License for the specific language governing permissions 11*2f172c55SRobert Thurlow * and limitations under the License. 12*2f172c55SRobert Thurlow * 13*2f172c55SRobert Thurlow * When distributing Covered Code, include this CDDL HEADER in each 14*2f172c55SRobert Thurlow * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2f172c55SRobert Thurlow * If applicable, add the following below this CDDL HEADER, with the 16*2f172c55SRobert Thurlow * fields enclosed by brackets "[]" replaced with your own identifying 17*2f172c55SRobert Thurlow * information: Portions Copyright [yyyy] [name of copyright owner] 18*2f172c55SRobert Thurlow * 19*2f172c55SRobert Thurlow * CDDL HEADER END 20*2f172c55SRobert Thurlow */ 21*2f172c55SRobert Thurlow 22*2f172c55SRobert Thurlow /* 23*2f172c55SRobert Thurlow * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*2f172c55SRobert Thurlow * Use is subject to license terms. 25*2f172c55SRobert Thurlow */ 26*2f172c55SRobert Thurlow 27*2f172c55SRobert Thurlow #include <stdio.h> 28*2f172c55SRobert Thurlow #include <unistd.h> 29*2f172c55SRobert Thurlow #include <strings.h> 30*2f172c55SRobert Thurlow #include <string.h> 31*2f172c55SRobert Thurlow #include <sys/types.h> 32*2f172c55SRobert Thurlow #include <sys/stat.h> 33*2f172c55SRobert Thurlow #include <sys/errno.h> 34*2f172c55SRobert Thurlow #include <limits.h> 35*2f172c55SRobert Thurlow #include <libnvpair.h> 36*2f172c55SRobert Thurlow #include <dlfcn.h> 37*2f172c55SRobert Thurlow #include <link.h> 38*2f172c55SRobert Thurlow #include <rp_plugin.h> 39*2f172c55SRobert Thurlow #include <fcntl.h> 40*2f172c55SRobert Thurlow #include <uuid/uuid.h> 41*2f172c55SRobert Thurlow #include <rpc/types.h> 42*2f172c55SRobert Thurlow #include <rpc/xdr.h> 43*2f172c55SRobert Thurlow #include <rpc/auth.h> 44*2f172c55SRobert Thurlow #include <rpc/clnt.h> 45*2f172c55SRobert Thurlow #include <rpc/rpc_msg.h> 46*2f172c55SRobert Thurlow #include <sys/param.h> 47*2f172c55SRobert Thurlow #include <nfs/nfs4.h> 48*2f172c55SRobert Thurlow #include <rpcsvc/nfs4_prot.h> 49*2f172c55SRobert Thurlow 50*2f172c55SRobert Thurlow /* 51*2f172c55SRobert Thurlow * str_to_utf8 - converts a null-terminated C string to a utf8 string 52*2f172c55SRobert Thurlow */ 53*2f172c55SRobert Thurlow utf8string * 54*2f172c55SRobert Thurlow str_to_utf8(char *nm, utf8string *str) 55*2f172c55SRobert Thurlow { 56*2f172c55SRobert Thurlow int len; 57*2f172c55SRobert Thurlow 58*2f172c55SRobert Thurlow if (str == NULL) 59*2f172c55SRobert Thurlow return (NULL); 60*2f172c55SRobert Thurlow 61*2f172c55SRobert Thurlow if (nm == NULL || *nm == '\0') { 62*2f172c55SRobert Thurlow str->utf8string_len = 0; 63*2f172c55SRobert Thurlow str->utf8string_val = NULL; 64*2f172c55SRobert Thurlow return (NULL); 65*2f172c55SRobert Thurlow } 66*2f172c55SRobert Thurlow 67*2f172c55SRobert Thurlow len = strlen(nm); 68*2f172c55SRobert Thurlow 69*2f172c55SRobert Thurlow str->utf8string_val = malloc(len); 70*2f172c55SRobert Thurlow if (str->utf8string_val == NULL) { 71*2f172c55SRobert Thurlow str->utf8string_len = 0; 72*2f172c55SRobert Thurlow return (NULL); 73*2f172c55SRobert Thurlow } 74*2f172c55SRobert Thurlow str->utf8string_len = len; 75*2f172c55SRobert Thurlow bcopy(nm, str->utf8string_val, len); 76*2f172c55SRobert Thurlow 77*2f172c55SRobert Thurlow return (str); 78*2f172c55SRobert Thurlow } 79*2f172c55SRobert Thurlow 80*2f172c55SRobert Thurlow /* 81*2f172c55SRobert Thurlow * Converts a utf8 string to a C string. 82*2f172c55SRobert Thurlow * kmem_allocs a new string if not supplied 83*2f172c55SRobert Thurlow */ 84*2f172c55SRobert Thurlow char * 85*2f172c55SRobert Thurlow utf8_to_str(utf8string *str, uint_t *lenp, char *s) 86*2f172c55SRobert Thurlow { 87*2f172c55SRobert Thurlow char *sp; 88*2f172c55SRobert Thurlow char *u8p; 89*2f172c55SRobert Thurlow int len; 90*2f172c55SRobert Thurlow int i; 91*2f172c55SRobert Thurlow 92*2f172c55SRobert Thurlow if (str == NULL) 93*2f172c55SRobert Thurlow return (NULL); 94*2f172c55SRobert Thurlow 95*2f172c55SRobert Thurlow u8p = str->utf8string_val; 96*2f172c55SRobert Thurlow len = str->utf8string_len; 97*2f172c55SRobert Thurlow if (len <= 0 || u8p == NULL) { 98*2f172c55SRobert Thurlow if (s) 99*2f172c55SRobert Thurlow *s = '\0'; 100*2f172c55SRobert Thurlow return (NULL); 101*2f172c55SRobert Thurlow } 102*2f172c55SRobert Thurlow 103*2f172c55SRobert Thurlow sp = s; 104*2f172c55SRobert Thurlow if (sp == NULL) 105*2f172c55SRobert Thurlow sp = malloc(len + 1); 106*2f172c55SRobert Thurlow if (sp == NULL) 107*2f172c55SRobert Thurlow return (NULL); 108*2f172c55SRobert Thurlow 109*2f172c55SRobert Thurlow /* 110*2f172c55SRobert Thurlow * At least check for embedded nulls 111*2f172c55SRobert Thurlow */ 112*2f172c55SRobert Thurlow for (i = 0; i < len; i++) { 113*2f172c55SRobert Thurlow sp[i] = u8p[i]; 114*2f172c55SRobert Thurlow if (u8p[i] == '\0') { 115*2f172c55SRobert Thurlow if (s == NULL) 116*2f172c55SRobert Thurlow free(sp); 117*2f172c55SRobert Thurlow return (NULL); 118*2f172c55SRobert Thurlow } 119*2f172c55SRobert Thurlow } 120*2f172c55SRobert Thurlow sp[len] = '\0'; 121*2f172c55SRobert Thurlow *lenp = len + 1; 122*2f172c55SRobert Thurlow 123*2f172c55SRobert Thurlow return (sp); 124*2f172c55SRobert Thurlow } 125*2f172c55SRobert Thurlow 126*2f172c55SRobert Thurlow void 127*2f172c55SRobert Thurlow print_referral_summary(fs_locations4 *fsl) 128*2f172c55SRobert Thurlow { 129*2f172c55SRobert Thurlow int i, j; 130*2f172c55SRobert Thurlow uint_t l; 131*2f172c55SRobert Thurlow char *s; 132*2f172c55SRobert Thurlow fs_location4 *fs; 133*2f172c55SRobert Thurlow 134*2f172c55SRobert Thurlow if (fsl == NULL) { 135*2f172c55SRobert Thurlow printf("NULL\n"); 136*2f172c55SRobert Thurlow return; 137*2f172c55SRobert Thurlow } 138*2f172c55SRobert Thurlow 139*2f172c55SRobert Thurlow for (i = 0; i < fsl->locations.locations_len; i++) { 140*2f172c55SRobert Thurlow if (i > 0) 141*2f172c55SRobert Thurlow printf("\n"); 142*2f172c55SRobert Thurlow fs = &fsl->locations.locations_val[i]; 143*2f172c55SRobert Thurlow for (j = 0; j < fs->server.server_len; j++) { 144*2f172c55SRobert Thurlow s = utf8_to_str(&fs->server.server_val[j], &l, NULL); 145*2f172c55SRobert Thurlow if (j > 0) 146*2f172c55SRobert Thurlow printf(","); 147*2f172c55SRobert Thurlow printf("%s", s ? s : ""); 148*2f172c55SRobert Thurlow if (s) 149*2f172c55SRobert Thurlow free(s); 150*2f172c55SRobert Thurlow } 151*2f172c55SRobert Thurlow printf(":"); 152*2f172c55SRobert Thurlow for (j = 0; j < fs->rootpath.pathname4_len; j++) { 153*2f172c55SRobert Thurlow s = utf8_to_str(&fs->rootpath.pathname4_val[j], 154*2f172c55SRobert Thurlow &l, NULL); 155*2f172c55SRobert Thurlow printf("/%s", s ? s : ""); 156*2f172c55SRobert Thurlow if (s) 157*2f172c55SRobert Thurlow free(s); 158*2f172c55SRobert Thurlow } 159*2f172c55SRobert Thurlow if (fs->rootpath.pathname4_len == 0) 160*2f172c55SRobert Thurlow printf("/"); 161*2f172c55SRobert Thurlow } 162*2f172c55SRobert Thurlow printf("\n"); 163*2f172c55SRobert Thurlow } 164*2f172c55SRobert Thurlow 165*2f172c55SRobert Thurlow /* 166*2f172c55SRobert Thurlow * There is a kernel copy of this routine in nfs4_srv.c. 167*2f172c55SRobert Thurlow * Changes should be kept in sync. 168*2f172c55SRobert Thurlow */ 169*2f172c55SRobert Thurlow static int 170*2f172c55SRobert Thurlow nfs4_create_components(char *path, component4 *comp4) 171*2f172c55SRobert Thurlow { 172*2f172c55SRobert Thurlow int slen, plen, ncomp; 173*2f172c55SRobert Thurlow char *ori_path, *nxtc, buf[MAXNAMELEN]; 174*2f172c55SRobert Thurlow 175*2f172c55SRobert Thurlow if (path == NULL) 176*2f172c55SRobert Thurlow return (0); 177*2f172c55SRobert Thurlow 178*2f172c55SRobert Thurlow plen = strlen(path) + 1; /* include the terminator */ 179*2f172c55SRobert Thurlow ori_path = path; 180*2f172c55SRobert Thurlow ncomp = 0; 181*2f172c55SRobert Thurlow 182*2f172c55SRobert Thurlow /* count number of components in the path */ 183*2f172c55SRobert Thurlow for (nxtc = path; nxtc < ori_path + plen; nxtc++) { 184*2f172c55SRobert Thurlow if (*nxtc == '/' || *nxtc == '\0' || *nxtc == '\n') { 185*2f172c55SRobert Thurlow if ((slen = nxtc - path) == 0) { 186*2f172c55SRobert Thurlow path = nxtc + 1; 187*2f172c55SRobert Thurlow continue; 188*2f172c55SRobert Thurlow } 189*2f172c55SRobert Thurlow 190*2f172c55SRobert Thurlow if (comp4 != NULL) { 191*2f172c55SRobert Thurlow bcopy(path, buf, slen); 192*2f172c55SRobert Thurlow buf[slen] = '\0'; 193*2f172c55SRobert Thurlow if (str_to_utf8(buf, &comp4[ncomp]) == NULL) 194*2f172c55SRobert Thurlow return (NULL); 195*2f172c55SRobert Thurlow } 196*2f172c55SRobert Thurlow 197*2f172c55SRobert Thurlow ncomp++; /* 1 valid component */ 198*2f172c55SRobert Thurlow path = nxtc + 1; 199*2f172c55SRobert Thurlow } 200*2f172c55SRobert Thurlow if (*nxtc == '\0' || *nxtc == '\n') 201*2f172c55SRobert Thurlow break; 202*2f172c55SRobert Thurlow } 203*2f172c55SRobert Thurlow 204*2f172c55SRobert Thurlow return (ncomp); 205*2f172c55SRobert Thurlow } 206*2f172c55SRobert Thurlow 207*2f172c55SRobert Thurlow /* 208*2f172c55SRobert Thurlow * There is a kernel copy of this routine in nfs4_srv.c. 209*2f172c55SRobert Thurlow * Changes should be kept in sync. 210*2f172c55SRobert Thurlow */ 211*2f172c55SRobert Thurlow int 212*2f172c55SRobert Thurlow make_pathname4(char *path, pathname4 *pathname) 213*2f172c55SRobert Thurlow { 214*2f172c55SRobert Thurlow int ncomp; 215*2f172c55SRobert Thurlow component4 *comp4; 216*2f172c55SRobert Thurlow 217*2f172c55SRobert Thurlow if (pathname == NULL) 218*2f172c55SRobert Thurlow return (0); 219*2f172c55SRobert Thurlow 220*2f172c55SRobert Thurlow if (path == NULL) { 221*2f172c55SRobert Thurlow pathname->pathname4_val = NULL; 222*2f172c55SRobert Thurlow pathname->pathname4_len = 0; 223*2f172c55SRobert Thurlow return (0); 224*2f172c55SRobert Thurlow } 225*2f172c55SRobert Thurlow 226*2f172c55SRobert Thurlow /* count number of components to alloc buffer */ 227*2f172c55SRobert Thurlow if ((ncomp = nfs4_create_components(path, NULL)) == 0) { 228*2f172c55SRobert Thurlow pathname->pathname4_val = NULL; 229*2f172c55SRobert Thurlow pathname->pathname4_len = 0; 230*2f172c55SRobert Thurlow return (0); 231*2f172c55SRobert Thurlow } 232*2f172c55SRobert Thurlow comp4 = calloc(ncomp * sizeof (component4), 1); 233*2f172c55SRobert Thurlow if (comp4 == NULL) { 234*2f172c55SRobert Thurlow pathname->pathname4_val = NULL; 235*2f172c55SRobert Thurlow pathname->pathname4_len = 0; 236*2f172c55SRobert Thurlow return (0); 237*2f172c55SRobert Thurlow } 238*2f172c55SRobert Thurlow 239*2f172c55SRobert Thurlow /* copy components into allocated buffer */ 240*2f172c55SRobert Thurlow ncomp = nfs4_create_components(path, comp4); 241*2f172c55SRobert Thurlow 242*2f172c55SRobert Thurlow pathname->pathname4_val = comp4; 243*2f172c55SRobert Thurlow pathname->pathname4_len = ncomp; 244*2f172c55SRobert Thurlow 245*2f172c55SRobert Thurlow return (ncomp); 246*2f172c55SRobert Thurlow } 247*2f172c55SRobert Thurlow 248*2f172c55SRobert Thurlow bool_t 249*2f172c55SRobert Thurlow xdr_component4(register XDR *xdrs, component4 *objp) 250*2f172c55SRobert Thurlow { 251*2f172c55SRobert Thurlow 252*2f172c55SRobert Thurlow if (!xdr_utf8string(xdrs, objp)) 253*2f172c55SRobert Thurlow return (FALSE); 254*2f172c55SRobert Thurlow return (TRUE); 255*2f172c55SRobert Thurlow } 256*2f172c55SRobert Thurlow 257*2f172c55SRobert Thurlow bool_t 258*2f172c55SRobert Thurlow xdr_utf8string(register XDR *xdrs, utf8string *objp) 259*2f172c55SRobert Thurlow { 260*2f172c55SRobert Thurlow 261*2f172c55SRobert Thurlow if (xdrs->x_op != XDR_FREE) 262*2f172c55SRobert Thurlow return (xdr_bytes(xdrs, (char **)&objp->utf8string_val, 263*2f172c55SRobert Thurlow (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING)); 264*2f172c55SRobert Thurlow return (TRUE); 265*2f172c55SRobert Thurlow } 266*2f172c55SRobert Thurlow 267*2f172c55SRobert Thurlow bool_t 268*2f172c55SRobert Thurlow xdr_pathname4(register XDR *xdrs, pathname4 *objp) 269*2f172c55SRobert Thurlow { 270*2f172c55SRobert Thurlow 271*2f172c55SRobert Thurlow if (!xdr_array(xdrs, (char **)&objp->pathname4_val, 272*2f172c55SRobert Thurlow (uint_t *)&objp->pathname4_len, NFS4_MAX_PATHNAME4, 273*2f172c55SRobert Thurlow sizeof (component4), (xdrproc_t)xdr_component4)) 274*2f172c55SRobert Thurlow return (FALSE); 275*2f172c55SRobert Thurlow return (TRUE); 276*2f172c55SRobert Thurlow } 277*2f172c55SRobert Thurlow 278*2f172c55SRobert Thurlow bool_t 279*2f172c55SRobert Thurlow xdr_fs_location4(register XDR *xdrs, fs_location4 *objp) 280*2f172c55SRobert Thurlow { 281*2f172c55SRobert Thurlow 282*2f172c55SRobert Thurlow if (xdrs->x_op == XDR_DECODE) { 283*2f172c55SRobert Thurlow objp->server.server_val = NULL; 284*2f172c55SRobert Thurlow objp->rootpath.pathname4_val = NULL; 285*2f172c55SRobert Thurlow } 286*2f172c55SRobert Thurlow if (!xdr_array(xdrs, (char **)&objp->server.server_val, 287*2f172c55SRobert Thurlow (uint_t *)&objp->server.server_len, ~0, 288*2f172c55SRobert Thurlow sizeof (utf8string), (xdrproc_t)xdr_utf8string)) 289*2f172c55SRobert Thurlow return (FALSE); 290*2f172c55SRobert Thurlow if (!xdr_pathname4(xdrs, &objp->rootpath)) 291*2f172c55SRobert Thurlow return (FALSE); 292*2f172c55SRobert Thurlow return (TRUE); 293*2f172c55SRobert Thurlow } 294*2f172c55SRobert Thurlow 295*2f172c55SRobert Thurlow bool_t 296*2f172c55SRobert Thurlow xdr_fs_locations4(register XDR *xdrs, fs_locations4 *objp) 297*2f172c55SRobert Thurlow { 298*2f172c55SRobert Thurlow 299*2f172c55SRobert Thurlow if (xdrs->x_op == XDR_DECODE) { 300*2f172c55SRobert Thurlow objp->fs_root.pathname4_len = 0; 301*2f172c55SRobert Thurlow objp->fs_root.pathname4_val = NULL; 302*2f172c55SRobert Thurlow objp->locations.locations_val = NULL; 303*2f172c55SRobert Thurlow } 304*2f172c55SRobert Thurlow if (!xdr_pathname4(xdrs, &objp->fs_root)) 305*2f172c55SRobert Thurlow return (FALSE); 306*2f172c55SRobert Thurlow if (!xdr_array(xdrs, (char **)&objp->locations.locations_val, 307*2f172c55SRobert Thurlow (uint_t *)&objp->locations.locations_len, ~0, 308*2f172c55SRobert Thurlow sizeof (fs_location4), (xdrproc_t)xdr_fs_location4)) 309*2f172c55SRobert Thurlow return (FALSE); 310*2f172c55SRobert Thurlow return (TRUE); 311*2f172c55SRobert Thurlow } 312