Home | History | Annotate | Download | only in autofs
      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