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