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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file can not be automatically generated by rpcgen from 28 * autofs_prot.x because of the xdr routines that provide readdir 29 * support, its own implementation of xdr_autofs_netbuf(). rpcgen will 30 * also generate xdr routines with recursion which should not be used 31 * in the kernel. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/kmem.h> 36 #include <sys/errno.h> 37 #include <sys/proc.h> 38 #include <sys/vfs.h> 39 #include <sys/vnode.h> 40 #include <sys/pathname.h> 41 #include <sys/cred.h> 42 #include <sys/mount.h> 43 #include <sys/cmn_err.h> 44 #include <sys/debug.h> 45 #include <sys/systm.h> 46 #include <rpc/types.h> 47 #include <rpc/xdr.h> 48 #include <rpc/auth.h> 49 #include <rpc/clnt.h> 50 #include <sys/ticotsord.h> 51 #include <sys/dirent.h> 52 #include <sys/sysmacros.h> 53 #include <fs/fs_subr.h> 54 #include <sys/fs/autofs.h> 55 56 bool_t xdr_autofs_netbuf(XDR *, struct netbuf *); 57 bool_t xdr_mounta(XDR *, struct mounta *); 58 59 bool_t 60 xdr_umntrequest(XDR *xdrs, umntrequest *objp) 61 { 62 bool_t more_data; 63 64 ASSERT(xdrs->x_op == XDR_ENCODE); 65 66 for (; objp != NULL; objp = objp->next) { 67 if (!xdr_bool_t(xdrs, &objp->isdirect)) 68 return (FALSE); 69 if (!xdr_string(xdrs, &objp->mntresource, AUTOFS_MAXPATHLEN)) 70 return (FALSE); 71 if (!xdr_string(xdrs, &objp->mntpnt, AUTOFS_MAXPATHLEN)) 72 return (FALSE); 73 if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN)) 74 return (FALSE); 75 if (!xdr_string(xdrs, &objp->mntopts, AUTOFS_MAXOPTSLEN)) 76 return (FALSE); 77 78 if (objp->next != NULL) 79 more_data = TRUE; 80 else 81 more_data = FALSE; 82 83 if (!xdr_bool(xdrs, &more_data)) 84 return (FALSE); 85 } 86 return (TRUE); 87 } 88 89 bool_t 90 xdr_umntres(XDR *xdrs, umntres *objp) 91 { 92 return (xdr_int(xdrs, &objp->status)); 93 } 94 95 bool_t 96 xdr_autofs_stat(XDR *xdrs, autofs_stat *objp) 97 { 98 if (!xdr_enum(xdrs, (enum_t *)objp)) 99 return (FALSE); 100 return (TRUE); 101 } 102 103 bool_t 104 xdr_autofs_action(XDR *xdrs, autofs_action *objp) 105 { 106 if (!xdr_enum(xdrs, (enum_t *)objp)) 107 return (FALSE); 108 return (TRUE); 109 } 110 111 bool_t 112 xdr_linka(XDR *xdrs, linka *objp) 113 { 114 if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN)) 115 return (FALSE); 116 if (!xdr_string(xdrs, &objp->link, AUTOFS_MAXPATHLEN)) 117 return (FALSE); 118 return (TRUE); 119 } 120 121 bool_t 122 xdr_autofs_args(XDR *xdrs, autofs_args *objp) 123 { 124 if (!xdr_autofs_netbuf(xdrs, &objp->addr)) 125 return (FALSE); 126 if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN)) 127 return (FALSE); 128 if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN)) 129 return (FALSE); 130 if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN)) 131 return (FALSE); 132 if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN)) 133 return (FALSE); 134 if (!xdr_string(xdrs, &objp->key, AUTOFS_MAXCOMPONENTLEN)) 135 return (FALSE); 136 if (!xdr_int(xdrs, &objp->mount_to)) 137 return (FALSE); 138 if (!xdr_int(xdrs, &objp->rpc_to)) 139 return (FALSE); 140 if (!xdr_int(xdrs, &objp->direct)) 141 return (FALSE); 142 return (TRUE); 143 } 144 145 bool_t 146 xdr_action_list_entry(XDR *xdrs, action_list_entry *objp) 147 { 148 if (!xdr_autofs_action(xdrs, &objp->action)) 149 return (FALSE); 150 switch (objp->action) { 151 case AUTOFS_MOUNT_RQ: 152 if (!xdr_mounta(xdrs, &objp->action_list_entry_u.mounta)) 153 return (FALSE); 154 break; 155 case AUTOFS_LINK_RQ: 156 if (!xdr_linka(xdrs, &objp->action_list_entry_u.linka)) 157 return (FALSE); 158 break; 159 default: 160 break; 161 } 162 return (TRUE); 163 } 164 165 bool_t 166 xdr_action_list(XDR *xdrs, action_list *objp) 167 { 168 bool_t more_data = TRUE; 169 bool_t status = TRUE; 170 action_list *p, *last; 171 172 ASSERT((xdrs->x_op == XDR_DECODE) || (xdrs->x_op == XDR_FREE)); 173 174 more_data = (objp != NULL); 175 p = objp; 176 177 if (xdrs->x_op == XDR_FREE) { 178 while (p != NULL) { 179 if (!xdr_action_list_entry(xdrs, &p->action)) 180 cmn_err(CE_WARN, "xdr_action_list: " 181 "action_list_entry free failed %p\n", 182 (void *)&p->action); 183 last = p; 184 p = p->next; 185 kmem_free(last, sizeof (*last)); 186 } 187 return (status); 188 } 189 190 while (more_data) { 191 if (!xdr_action_list_entry(xdrs, &p->action)) { 192 status = FALSE; 193 break; 194 } 195 196 if (!xdr_bool(xdrs, &more_data)) { 197 status = FALSE; 198 break; 199 } 200 201 if (more_data) { 202 p->next = kmem_zalloc(sizeof (action_list), KM_SLEEP); 203 p = p->next; 204 if (p == NULL) { 205 status = FALSE; 206 break; 207 } 208 } else 209 p->next = NULL; 210 } 211 return (status); 212 } 213 214 bool_t 215 xdr_autofs_netbuf(XDR *xdrs, struct netbuf *objp) 216 { 217 bool_t dummy; 218 219 if (!xdr_u_int(xdrs, (uint_t *)&objp->maxlen)) 220 return (FALSE); 221 dummy = xdr_bytes(xdrs, (char **)&(objp->buf), 222 (uint_t *)&(objp->len), objp->maxlen); 223 return (dummy); 224 } 225 226 bool_t 227 xdr_mounta(XDR *xdrs, struct mounta *objp) 228 { 229 if (!xdr_string(xdrs, &objp->spec, AUTOFS_MAXPATHLEN)) 230 return (FALSE); 231 if (!xdr_string(xdrs, &objp->dir, AUTOFS_MAXPATHLEN)) 232 return (FALSE); 233 if (!xdr_int(xdrs, &objp->flags)) 234 return (FALSE); 235 if (!xdr_string(xdrs, &objp->fstype, AUTOFS_MAXCOMPONENTLEN)) 236 return (FALSE); 237 if (!xdr_pointer(xdrs, (char **)&objp->dataptr, sizeof (autofs_args), 238 (xdrproc_t)xdr_autofs_args)) 239 return (FALSE); 240 /* 241 * The length is the original user-land length, not the 242 * length of the native kernel autofs_args structure provided 243 * after we decode the xdr buffer. So passing the user's idea of 244 * the length is wrong and we need to stuff the length field with 245 * the length of the native structure. 246 */ 247 if (!xdr_int(xdrs, &objp->datalen)) 248 return (FALSE); 249 if (xdrs->x_op == XDR_DECODE) 250 objp->datalen = sizeof (struct autofs_args); 251 if (!xdr_string(xdrs, &objp->optptr, AUTOFS_MAXOPTSLEN)) 252 return (FALSE); 253 if (!xdr_int(xdrs, &objp->optlen)) 254 return (FALSE); 255 ASSERT((xdrs->x_op == XDR_DECODE) || (xdrs->x_op == XDR_FREE)); 256 return (TRUE); 257 } 258 259 bool_t 260 xdr_autofs_res(XDR *xdrs, autofs_res *objp) 261 { 262 if (!xdr_enum(xdrs, (enum_t *)objp)) 263 return (FALSE); 264 return (TRUE); 265 } 266 267 bool_t 268 xdr_autofs_lookupargs(XDR *xdrs, autofs_lookupargs *objp) 269 { 270 if (!xdr_string(xdrs, &objp->map, AUTOFS_MAXPATHLEN)) 271 return (FALSE); 272 if (!xdr_string(xdrs, &objp->path, AUTOFS_MAXPATHLEN)) 273 return (FALSE); 274 if (!xdr_string(xdrs, &objp->name, AUTOFS_MAXCOMPONENTLEN)) 275 return (FALSE); 276 if (!xdr_string(xdrs, &objp->subdir, AUTOFS_MAXPATHLEN)) 277 return (FALSE); 278 if (!xdr_string(xdrs, &objp->opts, AUTOFS_MAXOPTSLEN)) 279 return (FALSE); 280 if (!xdr_bool_t(xdrs, &objp->isdirect)) 281 return (FALSE); 282 if (!xdr_u_int(xdrs, (uint_t *)&objp->uid)) 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 if (!xdr_u_int(xdrs, (uint_t *)&objp->uid)) 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