Home | History | Annotate | Download | only in rpc
      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 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved	*/
     29 
     30 /*
     31  * Portions of this source code were derived from Berkeley 4.3 BSD
     32  * under license from the Regents of the University of California.
     33  */
     34 
     35 #pragma ident	"@(#)svc_gen.c	1.49	05/06/08 SMI"
     36 
     37 #include <sys/types.h>
     38 #include <sys/sysmacros.h>
     39 #include <sys/param.h>
     40 #include <sys/cmn_err.h>
     41 #include <sys/debug.h>
     42 #include <rpc/types.h>
     43 #include <netinet/in.h>
     44 #include <rpc/auth.h>
     45 #include <rpc/clnt.h>
     46 #include <sys/tiuser.h>
     47 #include <sys/t_kuser.h>
     48 #include <rpc/svc.h>
     49 #include <sys/file.h>
     50 #include <sys/user.h>
     51 #include <sys/stream.h>
     52 #include <sys/strsubr.h>
     53 #include <sys/stropts.h>
     54 #include <sys/tihdr.h>
     55 #include <sys/timod.h>
     56 #include <sys/sunddi.h>
     57 #include <sys/fcntl.h>
     58 #include <sys/errno.h>
     59 
     60 /*
     61  * Create server-side kernel RPC `master' transport handle
     62  *
     63  * This is public interface for creation of a server RPC transport handle
     64  * for a given file descriptor. This function is called from nfs_svc()
     65  * and lm_svc().
     66  *
     67  * PSARC 2003/523 Contract Private Interface
     68  * svc_tli_kcreate
     69  * Changes must be reviewed by Solaris File Sharing
     70  * Changes must be communicated to contract-2003-523 (at) sun.com
     71  *
     72  * Arguments:
     73  * - fp		 - connection end point
     74  * - max_msgsize - max receive size
     75  * - netid	 - netid
     76  * - addrmask	 - address mask
     77  * - nxprt       - filled with outgoing transport handle
     78  * - sct	 - callout table to be registered with this transport handle
     79  * - closeproc	 - optional pointer to a closeproc for this transport or NULL
     80  * - id	         - RPC pool id (currently only NFS_SVCPOOL_ID or LM_SVCPOOL_ID)
     81  * - hotstream	 - very MT-hot flag (TRUE for NFS, FALSE for Lock Manager)
     82  *
     83  * Description:
     84  * - make sure rpcmod is on the stream
     85  * - call T_INFO_REQ to get the transport service type info
     86  * - call transport-type specific `create' routine (svc_clts_kcreate(),
     87  *   svc_cots_kcreate()) to create and initialize transport for the stream
     88  * - call svc_xprt_register() to register the transport handle into the
     89  *   service thread pool
     90  * - initialize transport-type independent fields (synchronization objects,
     91  *   thread counts, callout table, closeproc)
     92  * - optionally, for CLTS transports tell streams framework that the
     93  *   stream can be MT-hot
     94  * - call transport-type specific `start' function to tell rpcmod that
     95  *   the transport is ready to receive.
     96  */
     97 int
     98 svc_tli_kcreate(
     99 	struct file	*fp,		/* connection end point */
    100 	uint_t		max_msgsize,	/* max receive size */
    101 	char		*netid,
    102 	struct netbuf	*addrmask,
    103 	SVCMASTERXPRT	**nxprt,
    104 	SVC_CALLOUT_TABLE *sct,
    105 	void		(*closeproc)(const SVCMASTERXPRT *),
    106 	int		id,		/* thread pool  */
    107 	bool_t		hotstream)
    108 {
    109 	queue_t		*wq;
    110 	SVCMASTERXPRT	*xprt = NULL;	/* service handle */
    111 	int		retval;
    112 	struct strioctl strioc;
    113 	struct T_info_ack tinfo;
    114 	int		error;
    115 	void		**vp;
    116 	major_t		udpmaj;
    117 
    118 	RPCLOG(16, "svc_tli_kcreate: on file %p\n", (void *)fp);
    119 
    120 	if (fp == NULL || nxprt == NULL)
    121 		return (EINVAL);
    122 
    123 	if (fp->f_vnode->v_stream == NULL)
    124 		return (ENOSTR);
    125 
    126 	/*
    127 	 * Make sure that an RPC interface module is on the stream.
    128 	 */
    129 	wq = fp->f_vnode->v_stream->sd_wrq;
    130 	while ((wq = wq->q_next) != NULL) {
    131 		if (strcmp(wq->q_qinfo->qi_minfo->mi_idname, "rpcmod") == 0)
    132 			break;
    133 	}
    134 	if (!wq) {
    135 		RPCLOG0(1, "svc_tli_kcreate: no RPC module on stream\n");
    136 		return (EINVAL);
    137 	}
    138 
    139 	/*
    140 	 * Find out what type of transport this is.
    141 	 */
    142 	strioc.ic_cmd = TI_GETINFO;
    143 	strioc.ic_timout = -1;
    144 	strioc.ic_len = sizeof (tinfo);
    145 	strioc.ic_dp = (char *)&tinfo;
    146 	tinfo.PRIM_type = T_INFO_REQ;
    147 
    148 	error = strioctl(fp->f_vnode, I_STR, (intptr_t)&strioc, 0, K_TO_K,
    149 	    CRED(), &retval);
    150 	if (error || retval) {
    151 		RPCLOG(1, "svc_tli_kcreate: getinfo ioctl: %d\n", error);
    152 		return (error);
    153 	}
    154 
    155 	/*
    156 	 * Call transport-type specific `create' function.
    157 	 * It will allocate transport structure.
    158 	 */
    159 	switch (tinfo.SERV_type) {
    160 	case T_CLTS:
    161 		error = svc_clts_kcreate(fp, max_msgsize, &tinfo, &xprt);
    162 		break;
    163 	case T_COTS:
    164 	case T_COTS_ORD:
    165 		error = svc_cots_kcreate(fp, max_msgsize, &tinfo, &xprt);
    166 		break;
    167 	default:
    168 		RPCLOG(1, "svc_tli_kcreate: Bad service type %d\n",
    169 		    tinfo.SERV_type);
    170 		error = EINVAL;
    171 	}
    172 	if (error)
    173 		return (error);
    174 
    175 	/*
    176 	 * Initialize transport-type independent fields.
    177 	 */
    178 	xprt->xp_req_head = (mblk_t *)0;
    179 	xprt->xp_req_tail = (mblk_t *)0;
    180 	mutex_init(&xprt->xp_req_lock, NULL, MUTEX_DEFAULT, NULL);
    181 	mutex_init(&xprt->xp_thread_lock, NULL, MUTEX_DEFAULT, NULL);
    182 	xprt->xp_type = tinfo.SERV_type;
    183 	xprt->xp_threads = 0;
    184 	xprt->xp_detached_threads = 0;
    185 	xprt->xp_fp = fp;
    186 	xprt->xp_wq = wq;
    187 	xprt->xp_closeproc = closeproc;
    188 	xprt->xp_sct = sct;
    189 	xprt->xp_netid = NULL;
    190 	if (netid != NULL) {
    191 		xprt->xp_netid = kmem_alloc(strlen(netid) + 1, KM_SLEEP);
    192 		(void) strcpy(xprt->xp_netid, netid);
    193 	}
    194 
    195 	xprt->xp_addrmask.len = 0;
    196 	xprt->xp_addrmask.maxlen = 0;
    197 	xprt->xp_addrmask.buf = NULL;
    198 
    199 	if (addrmask != NULL) {
    200 		xprt->xp_addrmask = *addrmask;
    201 	}
    202 
    203 	/*
    204 	 * Register this transport handle after all fields have been
    205 	 * initialized. The registration can fail only if we try to register
    206 	 * with a non-existent pool (ENOENT) or a closing pool (EBUSY).
    207 	 */
    208 	if (error = svc_xprt_register(xprt, id)) {
    209 		/* if there was an addrmask, caller will delete it */
    210 		xprt->xp_addrmask.maxlen = 0;
    211 		SVC_DESTROY(xprt);
    212 		cmn_err(CE_WARN, "svc_tli_kcreate: xprt_register failed");
    213 
    214 		return (error);
    215 	}
    216 
    217 	/*
    218 	 * Set the private RPC cell in the module's data.
    219 	 */
    220 	vp = (void **)wq->q_ptr;
    221 	vp[0] = xprt;
    222 
    223 	/*
    224 	 * Inform the streams framework that the stream may be very MT hot.
    225 	 */
    226 	if (hotstream && tinfo.SERV_type == T_CLTS) {
    227 		udpmaj = ddi_name_to_major("udp");
    228 		if (udpmaj != (major_t)-1 &&
    229 			getmajor(fp->f_vnode->v_rdev) == udpmaj)
    230 			create_putlocks(wq, 1);
    231 	}
    232 
    233 	*nxprt = xprt;
    234 
    235 	/*
    236 	 * Tell rpcmod that the transport is fully initialized and
    237 	 * ready to process requests.
    238 	 */
    239 	SVC_START(xprt);
    240 
    241 	return (0);
    242 }
    243