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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This file can not be automatically generated by rpcgen from 30 * autofs_prot.x because of the xdr routines that provide readdir 31 * support, its own implementation of xdr_autofs_netbuf(). rpcgen will 32 * also generate xdr routines with recursion which should not be used 33 * in the kernel. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/kmem.h> 38 #include <sys/errno.h> 39 #include <sys/proc.h> 40 #include <sys/vfs.h> 41 #include <sys/vnode.h> 42 #include <sys/pathname.h> 43 #include <sys/cred.h> 44 #include <sys/mount.h> 45 #include <sys/cmn_err.h> 46 #include <sys/debug.h> 47 #include <sys/systm.h> 48 #include <rpc/types.h> 49 #include <rpc/xdr.h> 50 #include <rpc/auth.h> 51 #include <rpc/clnt.h> 52 #include <sys/ticotsord.h> 53 #include <sys/dirent.h> 54 #include <sys/sysmacros.h> 55 #include <fs/fs_subr.h> 56 #include <sys/fs/autofs.h> 57 58 bool_t xdr_autofs_netbuf(XDR *, struct netbuf *); 59 bool_t xdr_mounta(XDR *, struct mounta *); 60 61 bool_t 62 xdr_umntrequest(XDR *xdrs, umntrequest *objp) 63 { 64 bool_t more_data; 65 66 ASSERT(xdrs->x_op == XDR_ENCODE); 67 68 for (; objp != NULL; objp = objp->next) { 69 if (!xdr_bool_t(xdrs, &objp->isdirect)) 70 return (FALSE); 71 if (!xdr_string(xdrs, &objp->mntresource, AUTOFS_MAXPATHLEN)) 72 return (FALSE); 73 if (!xdr_string(xdrs, &objp->mntpnt, AUTOFS_MAXPATHLEN)) 74 return (FALSE); 75 if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN)) 76 return (FALSE); 77 if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN)) 78 return (FALSE); 79 80 if (objp->next != NULL) 81 more_data = TRUE; 82 else 83 more_data = FALSE; 84 85 if (!xdr_bool(xdrs, &more_data)) 86 return (FALSE); 87 } 88 return (TRUE); 89 } 90 91 bool_t 92 xdr_umntres(XDR *xdrs, umntres *objp) 93 { 94 return (xdr_int(xdrs, &objp->status)); 95 } 96 97 bool_t 98 xdr_autofs_stat(XDR *xdrs, autofs_stat *objp) 99 { 100 if (!xdr_enum(xdrs, (enum_t *)objp)) 101 return (FALSE); 102 return (TRUE); 103 } 104 105 bool_t 106 xdr_autofs_action(XDR *xdrs, autofs_action *objp) 107 { 108 if (!xdr_enum(xdrs, (enum_t *)objp)) 109 return (FALSE); 110 return (TRUE); 111 } 112 113 bool_t 114 xdr_linka(XDR *xdrs, linka *objp) 115 { 116 if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN)) 117 return (FALSE); 118 if (!xdr_string(xdrs, &objp->link, AUTOFS_MAXPATHLEN)) 119 return (FALSE); 120 return (TRUE); 121 } 122 123 bool_t 124 xdr_autofs_args(XDR *xdrs, autofs_args *objp) 125 { 126 if (!xdr_autofs_netbuf(xdrs, &objp->addr)) 127 return (FALSE); 128 if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN)) 129 return (FALSE); 130 if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN)) 131 return (FALSE); 132 if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN)) 133 return (FALSE); 134 if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN)) 135 return (FALSE); 136 if (!xdr_string(xdrs, &objp->key, AUTOFS_MAXCOMPONENTLEN)) 137 return (FALSE); 138 if (!xdr_int(xdrs, &objp->mount_to)) 139 return (FALSE); 140 if (!xdr_int(xdrs, &objp->rpc_to)) 141 return (FALSE); 142 if (!xdr_int(xdrs, &objp->direct)) 143 return (FALSE); 144 return (TRUE); 145 } 146 147 bool_t 148 xdr_action_list_entry(XDR *xdrs, action_list_entry *objp) 149 { 150 if (!xdr_autofs_action(xdrs, &objp->action)) 151 return (FALSE); 152 switch (objp->action) { 153 case AUTOFS_MOUNT_RQ: 154 if (!xdr_mounta(xdrs, &objp->action_list_entry_u.mounta)) 155 return (FALSE); 156 break; 157 case AUTOFS_LINK_RQ: 158 if (!xdr_linka(xdrs, &objp->action_list_entry_u.linka)) 159 return (FALSE); 160 break; 161 default: 162 break; 163 } 164 return (TRUE); 165 } 166 167 bool_t 168 xdr_action_list(XDR *xdrs, action_list *objp) 169 { 170 bool_t more_data = TRUE; 171 bool_t status = TRUE; 172 action_list *p; 173 174 ASSERT((xdrs->x_op == XDR_DECODE) || (xdrs->x_op == XDR_FREE)); 175 176 more_data = (objp != NULL); 177 p = objp; 178 179 if (xdrs->x_op == XDR_FREE) 180 goto free; 181 182 while (more_data) { 183 if (!xdr_action_list_entry(xdrs, &p->action)) 184 goto free; 185 186 if (!xdr_bool(xdrs, &more_data)) 187 goto free; 188 189 if (more_data) { 190 p->next = kmem_zalloc(sizeof (action_list), KM_SLEEP); 191 p = p->next; 192 if (p == NULL) { 193 status = FALSE; 194 goto free; 195 } 196 } else 197 p->next = NULL; 198 } 199 return (TRUE); 200 201 free: 202 for (p = objp; p != NULL; ) { 203 if (!xdr_action_list_entry(xdrs, &objp->action)) 204 cmn_err(CE_WARN, "xdr_action_list: " 205 "action_list_entry free failed %p\n", 206 (void *)&objp->action); 207 p = p->next; 208 kmem_free(objp, sizeof (*objp)); 209 objp = p; 210 } 211 objp = NULL; 212 213 return (status); 214 } 215 216 bool_t 217 xdr_autofs_netbuf(XDR *xdrs, struct netbuf *objp) 218 { 219 bool_t dummy; 220 221 if (!xdr_u_int(xdrs, (uint_t *)&objp->maxlen)) 222 return (FALSE); 223 dummy = xdr_bytes(xdrs, (char **)&(objp->buf), 224 (uint_t *)&(objp->len), objp->maxlen); 225 return (dummy); 226 } 227 228 bool_t 229 xdr_mounta(XDR *xdrs, struct mounta *objp) 230 { 231 if (!xdr_string(xdrs, &objp->spec, AUTOFS_MAXPATHLEN)) 232 return (FALSE); 233 if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN)) 234 return (FALSE); 235 if (!xdr_int(xdrs, &objp->flags)) 236 return (FALSE); 237 if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN)) 238 return (FALSE); 239 if (!xdr_pointer(xdrs, (char **)&objp->dataptr, sizeof (autofs_args), 240 (xdrproc_t)xdr_autofs_args)) 241 return (FALSE); 242 /* 243 * The length is the original user-land length, not the 244 * length of the native kernel autofs_args structure provided 245 * after we decode the xdr buffer. So passing the user's idea of 246 * the length is wrong and we need to stuff the length field with 247 * the length of the native structure. 248 */ 249 if (!xdr_int(xdrs, &objp->datalen)) 250 return (FALSE); 251 if (xdrs->x_op == XDR_DECODE) 252 objp->datalen = sizeof (struct autofs_args); 253 if (!xdr_string(xdrs, &objp->optptr, AUTOFS_MAXOPTSLEN)) 254 return (FALSE); 255 if (!xdr_int(xdrs, &objp->optlen)) 256 return (FALSE); 257 ASSERT((xdrs->x_op == XDR_DECODE) || (xdrs->x_op == XDR_FREE)); 258 return (TRUE); 259 } 260 261 bool_t 262 xdr_autofs_res(XDR *xdrs, autofs_res *objp) 263 { 264 if (!xdr_enum(xdrs, (enum_t *)objp)) 265 return (FALSE); 266 return (TRUE); 267 } 268 269 bool_t 270 xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp) 271 { 272 if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN)) 273 return (FALSE); 274 if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN)) 275 return (FALSE); 276 if (!xdr_string(xdrs, &objp->name, AUTOFS_MAXCOMPONENTLEN)) 277 return (FALSE); 278 if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN)) 279 return (FALSE); 280 if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN)) 281 return (FALSE); 282 if (!xdr_bool_t(xdrs, &objp->isdirect)) 283 return (FALSE); 284 return (TRUE); 285 } 286 287 bool_t 288 xdr_mount_result_type(XDR *xdrs, mount_result_type *objp) 289 { 290 if (!xdr_autofs_stat(xdrs, &objp->status)) 291 return (FALSE); 292 switch (objp->status) { 293 case AUTOFS_ACTION: 294 if (!xdr_pointer(xdrs, 295 (char **)&objp->mount_result_type_u.list, 296 sizeof (action_list), (xdrproc_t)xdr_action_list)) 297 return (FALSE); 298 break; 299 case AUTOFS_DONE: 300 if (!xdr_int(xdrs, &objp->mount_result_type_u.error)) 301 return (FALSE); 302 break; 303 } 304 return (TRUE); 305 } 306 307 bool_t 308 xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp) 309 { 310 if (!xdr_mount_result_type(xdrs, &objp->mr_type)) 311 return (FALSE); 312 if (!xdr_int(xdrs, &objp->mr_verbose)) 313 return (FALSE); 314 return (TRUE); 315 } 316 317 bool_t 318 xdr_lookup_result_type(XDR *xdrs, lookup_result_type *objp) 319 { 320 if (!xdr_autofs_action(xdrs, &objp->action)) 321 return (FALSE); 322 switch (objp->action) { 323 case AUTOFS_LINK_RQ: 324 if (!xdr_linka(xdrs, &objp->lookup_result_type_u.lt_linka)) 325 return (FALSE); 326 break; 327 default: 328 break; 329 } 330 return (TRUE); 331 } 332 333 bool_t 334 xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp) 335 { 336 if (!xdr_autofs_res(xdrs, &objp->lu_res)) 337 return (FALSE); 338 if (!xdr_lookup_result_type(xdrs, &objp->lu_type)) 339 return (FALSE); 340 if (!xdr_int(xdrs, &objp->lu_verbose)) 341 return (FALSE); 342 return (TRUE); 343 } 344 345 bool_t 346 xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp) 347 { 348 if (!xdr_string(xdrs, &objp->rda_map, AUTOFS_MAXPATHLEN)) 349 return (FALSE); 350 if (!xdr_u_int(xdrs, &objp->rda_offset)) 351 return (FALSE); 352 if (!xdr_u_int(xdrs, &objp->rda_count)) 353 return (FALSE); 354 return (TRUE); 355 } 356 357 /* 358 * Directory read reply: 359 * union (enum autofs_res) { 360 * AUTOFS_OK: entlist; 361 * boolean eof; 362 * default: 363 * } 364 * 365 * Directory entries 366 * struct direct { 367 * off_t d_off; * offset of next entry * 368 * u_long d_fileno; * inode number of entry * 369 * ushort_t d_reclen; * length of this record * 370 * ushort_t d_namlen; * length of string in d_name * 371 * char d_name[MAXNAMLEN + 1]; * name no longer than this * 372 * }; 373 * are on the wire as: 374 * union entlist (boolean valid) { 375 * TRUE: struct otw_dirent; 376 * uint_t nxtoffset; 377 * union entlist; 378 * FALSE: 379 * } 380 * where otw_dirent is: 381 * struct dirent { 382 * uint_t de_fid; 383 * string de_name<AUTOFS_MAXPATHLEN>; 384 * } 385 */ 386 387 #ifdef nextdp 388 #undef nextdp 389 #endif 390 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 391 392 /* 393 * ENCODE ONLY 394 */ 395 bool_t 396 xdr_autofs_putrddirres(XDR *xdrs, struct autofsrddir *rddir, uint_t reqsize) 397 { 398 struct dirent64 *dp; 399 char *name; 400 int size; 401 uint_t namlen; 402 bool_t true = TRUE; 403 bool_t false = FALSE; 404 int entrysz; 405 int tofit; 406 int bufsize; 407 uint_t ino, off; 408 409 bufsize = 1 * BYTES_PER_XDR_UNIT; 410 for (size = rddir->rddir_size, dp = rddir->rddir_entries; 411 size > 0; 412 /* LINTED pointer alignment */ 413 size -= dp->d_reclen, dp = nextdp(dp)) { 414 if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */) 415 return (FALSE); 416 if (dp->d_ino == 0) 417 continue; 418 name = dp->d_name; 419 namlen = (uint_t)strlen(name); 420 ino = (uint_t)dp->d_ino; 421 off = (uint_t)dp->d_off; 422 entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT + 423 roundup(namlen, BYTES_PER_XDR_UNIT); 424 tofit = entrysz + 2 * BYTES_PER_XDR_UNIT; 425 if (bufsize + tofit > reqsize) { 426 rddir->rddir_eof = FALSE; 427 break; 428 } 429 if (!xdr_bool(xdrs, &true) || 430 !xdr_u_int(xdrs, &ino) || 431 !xdr_bytes(xdrs, &name, &namlen, AUTOFS_MAXPATHLEN) || 432 !xdr_u_int(xdrs, &off)) { 433 return (FALSE); 434 } 435 bufsize += entrysz; 436 } 437 if (!xdr_bool(xdrs, &false)) 438 return (FALSE); 439 if (!xdr_bool(xdrs, &rddir->rddir_eof)) 440 return (FALSE); 441 return (TRUE); 442 } 443 444 445 /* 446 * DECODE ONLY 447 */ 448 bool_t 449 xdr_autofs_getrddirres(XDR *xdrs, struct autofsrddir *rddir) 450 { 451 struct dirent64 *dp; 452 uint_t namlen; 453 int size; 454 bool_t valid; 455 uint_t offset; 456 uint_t fileid; 457 458 offset = (uint_t)-1; 459 460 size = rddir->rddir_size; 461 dp = rddir->rddir_entries; 462 for (;;) { 463 if (!xdr_bool(xdrs, &valid)) 464 return (FALSE); 465 if (!valid) 466 break; 467 if (!xdr_u_int(xdrs, &fileid) || 468 !xdr_u_int(xdrs, &namlen)) 469 return (FALSE); 470 if (DIRENT64_RECLEN(namlen) > size) { 471 rddir->rddir_eof = FALSE; 472 goto bufovflw; 473 } 474 if (!xdr_opaque(xdrs, dp->d_name, namlen)|| 475 !xdr_u_int(xdrs, &offset)) 476 return (FALSE); 477 dp->d_ino = fileid; 478 dp->d_reclen = (ushort_t)DIRENT64_RECLEN(namlen); 479 bzero(&dp->d_name[namlen], 480 DIRENT64_NAMELEN(dp->d_reclen) - namlen); 481 dp->d_off = offset; 482 size -= dp->d_reclen; 483 /* LINTED pointer alignment */ 484 dp = nextdp(dp); 485 } 486 if (!xdr_bool(xdrs, &rddir->rddir_eof)) 487 return (FALSE); 488 bufovflw: 489 rddir->rddir_size = (uint_t)((char *)dp - (char *)rddir->rddir_entries); 490 rddir->rddir_offset = offset; 491 return (TRUE); 492 } 493 494 bool_t 495 xdr_autofs_rddirres(XDR *xdrs, autofs_rddirres *objp) 496 { 497 if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status)) 498 return (FALSE); 499 if (objp->rd_status != AUTOFS_OK) 500 return (TRUE); 501 if (xdrs->x_op == XDR_ENCODE) 502 return (xdr_autofs_putrddirres(xdrs, 503 (struct autofsrddir *)&objp->rd_rddir, objp->rd_bufsize)); 504 else if (xdrs->x_op == XDR_DECODE) 505 return (xdr_autofs_getrddirres(xdrs, 506 (struct autofsrddir *)&objp->rd_rddir)); 507 return (FALSE); 508 } 509