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