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