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 2007 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 if (!xdr_u_int(xdrs, (uint_t *)&objp->uid)) 285 return (FALSE); 286 return (TRUE); 287 } 288 289 bool_t 290 xdr_mount_result_type(XDR *xdrs, mount_result_type *objp) 291 { 292 if (!xdr_autofs_stat(xdrs, &objp->status)) 293 return (FALSE); 294 switch (objp->status) { 295 case AUTOFS_ACTION: 296 if (!xdr_pointer(xdrs, 297 (char **)&objp->mount_result_type_u.list, 298 sizeof (action_list), (xdrproc_t)xdr_action_list)) 299 return (FALSE); 300 break; 301 case AUTOFS_DONE: 302 if (!xdr_int(xdrs, &objp->mount_result_type_u.error)) 303 return (FALSE); 304 break; 305 } 306 return (TRUE); 307 } 308 309 bool_t 310 xdr_autofs_mountres(XDR *xdrs, autofs_mountres *objp) 311 { 312 if (!xdr_mount_result_type(xdrs, &objp->mr_type)) 313 return (FALSE); 314 if (!xdr_int(xdrs, &objp->mr_verbose)) 315 return (FALSE); 316 return (TRUE); 317 } 318 319 bool_t 320 xdr_lookup_result_type(XDR *xdrs, lookup_result_type *objp) 321 { 322 if (!xdr_autofs_action(xdrs, &objp->action)) 323 return (FALSE); 324 switch (objp->action) { 325 case AUTOFS_LINK_RQ: 326 if (!xdr_linka(xdrs, &objp->lookup_result_type_u.lt_linka)) 327 return (FALSE); 328 break; 329 default: 330 break; 331 } 332 return (TRUE); 333 } 334 335 bool_t 336 xdr_autofs_lookupres(XDR *xdrs, autofs_lookupres *objp) 337 { 338 if (!xdr_autofs_res(xdrs, &objp->lu_res)) 339 return (FALSE); 340 if (!xdr_lookup_result_type(xdrs, &objp->lu_type)) 341 return (FALSE); 342 if (!xdr_int(xdrs, &objp->lu_verbose)) 343 return (FALSE); 344 return (TRUE); 345 } 346 347 bool_t 348 xdr_autofs_rddirargs(XDR *xdrs, autofs_rddirargs *objp) 349 { 350 if (!xdr_string(xdrs, &objp->rda_map, AUTOFS_MAXPATHLEN)) 351 return (FALSE); 352 if (!xdr_u_int(xdrs, &objp->rda_offset)) 353 return (FALSE); 354 if (!xdr_u_int(xdrs, &objp->rda_count)) 355 return (FALSE); 356 if (!xdr_u_int(xdrs, (uint_t *)&objp->uid)) 357 return (FALSE); 358 return (TRUE); 359 } 360 361 /* 362 * Directory read reply: 363 * union (enum autofs_res) { 364 * AUTOFS_OK: entlist; 365 * boolean eof; 366 * default: 367 * } 368 * 369 * Directory entries 370 * struct direct { 371 * off_t d_off; * offset of next entry * 372 * u_long d_fileno; * inode number of entry * 373 * ushort_t d_reclen; * length of this record * 374 * ushort_t d_namlen; * length of string in d_name * 375 * char d_name[MAXNAMLEN + 1]; * name no longer than this * 376 * }; 377 * are on the wire as: 378 * union entlist (boolean valid) { 379 * TRUE: struct otw_dirent; 380 * uint_t nxtoffset; 381 * union entlist; 382 * FALSE: 383 * } 384 * where otw_dirent is: 385 * struct dirent { 386 * uint_t de_fid; 387 * string de_name<AUTOFS_MAXPATHLEN>; 388 * } 389 */ 390 391 #ifdef nextdp 392 #undef nextdp 393 #endif 394 #define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen)) 395 396 /* 397 * ENCODE ONLY 398 */ 399 bool_t 400 xdr_autofs_putrddirres(XDR *xdrs, struct autofsrddir *rddir, uint_t reqsize) 401 { 402 struct dirent64 *dp; 403 char *name; 404 int size; 405 uint_t namlen; 406 bool_t true = TRUE; 407 bool_t false = FALSE; 408 int entrysz; 409 int tofit; 410 int bufsize; 411 uint_t ino, off; 412 413 bufsize = 1 * BYTES_PER_XDR_UNIT; 414 for (size = rddir->rddir_size, dp = rddir->rddir_entries; 415 size > 0; 416 /* LINTED pointer alignment */ 417 size -= dp->d_reclen, dp = nextdp(dp)) { 418 if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */) 419 return (FALSE); 420 if (dp->d_ino == 0) 421 continue; 422 name = dp->d_name; 423 namlen = (uint_t)strlen(name); 424 ino = (uint_t)dp->d_ino; 425 off = (uint_t)dp->d_off; 426 entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT + 427 roundup(namlen, BYTES_PER_XDR_UNIT); 428 tofit = entrysz + 2 * BYTES_PER_XDR_UNIT; 429 if (bufsize + tofit > reqsize) { 430 rddir->rddir_eof = FALSE; 431 break; 432 } 433 if (!xdr_bool(xdrs, &true) || 434 !xdr_u_int(xdrs, &ino) || 435 !xdr_bytes(xdrs, &name, &namlen, AUTOFS_MAXPATHLEN) || 436 !xdr_u_int(xdrs, &off)) { 437 return (FALSE); 438 } 439 bufsize += entrysz; 440 } 441 if (!xdr_bool(xdrs, &false)) 442 return (FALSE); 443 if (!xdr_bool(xdrs, &rddir->rddir_eof)) 444 return (FALSE); 445 return (TRUE); 446 } 447 448 449 /* 450 * DECODE ONLY 451 */ 452 bool_t 453 xdr_autofs_getrddirres(XDR *xdrs, struct autofsrddir *rddir) 454 { 455 struct dirent64 *dp; 456 uint_t namlen; 457 int size; 458 bool_t valid; 459 uint_t offset; 460 uint_t fileid; 461 462 offset = (uint_t)-1; 463 464 size = rddir->rddir_size; 465 dp = rddir->rddir_entries; 466 for (;;) { 467 if (!xdr_bool(xdrs, &valid)) 468 return (FALSE); 469 if (!valid) 470 break; 471 if (!xdr_u_int(xdrs, &fileid) || 472 !xdr_u_int(xdrs, &namlen)) 473 return (FALSE); 474 if (DIRENT64_RECLEN(namlen) > size) { 475 rddir->rddir_eof = FALSE; 476 goto bufovflw; 477 } 478 if (!xdr_opaque(xdrs, dp->d_name, namlen)|| 479 !xdr_u_int(xdrs, &offset)) 480 return (FALSE); 481 dp->d_ino = fileid; 482 dp->d_reclen = (ushort_t)DIRENT64_RECLEN(namlen); 483 bzero(&dp->d_name[namlen], 484 DIRENT64_NAMELEN(dp->d_reclen) - namlen); 485 dp->d_off = offset; 486 size -= dp->d_reclen; 487 /* LINTED pointer alignment */ 488 dp = nextdp(dp); 489 } 490 if (!xdr_bool(xdrs, &rddir->rddir_eof)) 491 return (FALSE); 492 bufovflw: 493 rddir->rddir_size = (uint_t)((char *)dp - (char *)rddir->rddir_entries); 494 rddir->rddir_offset = offset; 495 return (TRUE); 496 } 497 498 bool_t 499 xdr_autofs_rddirres(XDR *xdrs, autofs_rddirres *objp) 500 { 501 if (!xdr_enum(xdrs, (enum_t *)&objp->rd_status)) 502 return (FALSE); 503 if (objp->rd_status != AUTOFS_OK) 504 return (TRUE); 505 if (xdrs->x_op == XDR_ENCODE) 506 return (xdr_autofs_putrddirres(xdrs, 507 (struct autofsrddir *)&objp->rd_rddir, objp->rd_bufsize)); 508 else if (xdrs->x_op == XDR_DECODE) 509 return (xdr_autofs_getrddirres(xdrs, 510 (struct autofsrddir *)&objp->rd_rddir)); 511 return (FALSE); 512 } 513