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 *
str_to_utf8(char * nm,utf8string * str)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 *
utf8_to_str(utf8string * str,uint_t * lenp,char * s)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
print_referral_summary(fs_locations4 * fsl)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
nfs4_create_components(char * path,component4 * comp4)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
make_pathname4(char * path,pathname4 * pathname)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
xdr_component4(register XDR * xdrs,component4 * objp)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
xdr_utf8string(register XDR * xdrs,utf8string * objp)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
xdr_pathname4(register XDR * xdrs,pathname4 * objp)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
xdr_fs_location4(register XDR * xdrs,fs_location4 * objp)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
xdr_fs_locations4(register XDR * xdrs,fs_locations4 * objp)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