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 "%Z%%M% %I% %E% 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@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