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