1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1998 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* 31*0Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 32*0Sstevel@tonic-gate * The Regents of the University of California 33*0Sstevel@tonic-gate * All Rights Reserved 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 36*0Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 37*0Sstevel@tonic-gate * contributors. 38*0Sstevel@tonic-gate */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * Kernel TLI-like function to allow a trasnport endpoint to initiate a 44*0Sstevel@tonic-gate * connection to another transport endpoint. This function will wait for 45*0Sstevel@tonic-gate * an ack and a T_CONN_CON before returning. 46*0Sstevel@tonic-gate * 47*0Sstevel@tonic-gate * Returns: 48*0Sstevel@tonic-gate * 0 on success, and if rcvcall is non-NULL it shall be 49*0Sstevel@tonic-gate * filled with the connection confirm data. 50*0Sstevel@tonic-gate * Otherwise a positive error code. 51*0Sstevel@tonic-gate */ 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #include <sys/param.h> 54*0Sstevel@tonic-gate #include <sys/types.h> 55*0Sstevel@tonic-gate #include <sys/user.h> 56*0Sstevel@tonic-gate #include <sys/file.h> 57*0Sstevel@tonic-gate #include <sys/vnode.h> 58*0Sstevel@tonic-gate #include <sys/errno.h> 59*0Sstevel@tonic-gate #include <sys/stream.h> 60*0Sstevel@tonic-gate #include <sys/ioctl.h> 61*0Sstevel@tonic-gate #include <sys/stropts.h> 62*0Sstevel@tonic-gate #include <sys/tihdr.h> 63*0Sstevel@tonic-gate #include <sys/timod.h> 64*0Sstevel@tonic-gate #include <sys/tiuser.h> 65*0Sstevel@tonic-gate #include <sys/t_kuser.h> 66*0Sstevel@tonic-gate #include <sys/strsubr.h> 67*0Sstevel@tonic-gate #include <sys/sysmacros.h> 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate int 71*0Sstevel@tonic-gate t_kconnect(TIUSER *tiptr, struct t_call *sndcall, struct t_call *rcvcall) 72*0Sstevel@tonic-gate { 73*0Sstevel@tonic-gate int len; 74*0Sstevel@tonic-gate int msgsz; 75*0Sstevel@tonic-gate size_t hdrsz; 76*0Sstevel@tonic-gate struct T_conn_req *creq; 77*0Sstevel@tonic-gate union T_primitives *pptr; 78*0Sstevel@tonic-gate mblk_t *nbp; 79*0Sstevel@tonic-gate file_t *fp; 80*0Sstevel@tonic-gate mblk_t *bp; 81*0Sstevel@tonic-gate int error; 82*0Sstevel@tonic-gate int flag; 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate error = 0; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate fp = tiptr->fp; 87*0Sstevel@tonic-gate msgsz = (int)TCONNREQSZ; 88*0Sstevel@tonic-gate while (!(bp = allocb(msgsz + sndcall->addr.len + sndcall->opt.len, 89*0Sstevel@tonic-gate BPRI_LO))) { 90*0Sstevel@tonic-gate if (strwaitbuf(msgsz + sndcall->addr.len + sndcall->opt.len, 91*0Sstevel@tonic-gate BPRI_LO)) 92*0Sstevel@tonic-gate return (ENOSR); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate /* LINTED pointer alignment */ 96*0Sstevel@tonic-gate creq = (struct T_conn_req *)bp->b_wptr; 97*0Sstevel@tonic-gate creq->PRIM_type = T_CONN_REQ; 98*0Sstevel@tonic-gate creq->DEST_length = (t_scalar_t)sndcall->addr.len; 99*0Sstevel@tonic-gate creq->OPT_length = (t_scalar_t)sndcall->opt.len; 100*0Sstevel@tonic-gate 101*0Sstevel@tonic-gate if (sndcall->addr.len) { 102*0Sstevel@tonic-gate bcopy(sndcall->addr.buf, (bp->b_wptr+msgsz), sndcall->addr.len); 103*0Sstevel@tonic-gate creq->DEST_offset = (t_scalar_t)msgsz; 104*0Sstevel@tonic-gate msgsz += sndcall->addr.len; 105*0Sstevel@tonic-gate } else 106*0Sstevel@tonic-gate creq->DEST_offset = (t_scalar_t)0; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate if (sndcall->opt.len) { 109*0Sstevel@tonic-gate bcopy(sndcall->opt.buf, (bp->b_wptr+msgsz), sndcall->opt.len); 110*0Sstevel@tonic-gate creq->OPT_offset = (t_scalar_t)msgsz; 111*0Sstevel@tonic-gate msgsz += sndcall->opt.len; 112*0Sstevel@tonic-gate } else 113*0Sstevel@tonic-gate creq->OPT_offset = (t_scalar_t)0; 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate bp->b_datap->db_type = M_PROTO; 116*0Sstevel@tonic-gate bp->b_wptr += msgsz; 117*0Sstevel@tonic-gate 118*0Sstevel@tonic-gate /* 119*0Sstevel@tonic-gate * copy the users data, if any. 120*0Sstevel@tonic-gate */ 121*0Sstevel@tonic-gate if (sndcall->udata.len) { 122*0Sstevel@tonic-gate /* 123*0Sstevel@tonic-gate * if CO then we would allocate a data block and 124*0Sstevel@tonic-gate * put the users connect data into it. 125*0Sstevel@tonic-gate */ 126*0Sstevel@tonic-gate KTLILOG(1, 127*0Sstevel@tonic-gate "Attempt to send connectionless data on T_CONN_REQ\n", 0); 128*0Sstevel@tonic-gate freemsg(bp); 129*0Sstevel@tonic-gate return (EPROTO); 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gate flag = fp->f_flag; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * send it 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate if ((error = tli_send(tiptr, bp, flag)) != 0) 138*0Sstevel@tonic-gate return (error); 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate /* 141*0Sstevel@tonic-gate * wait for acknowledgment 142*0Sstevel@tonic-gate */ 143*0Sstevel@tonic-gate if ((error = get_ok_ack(tiptr, T_CONN_REQ, flag)) != 0) 144*0Sstevel@tonic-gate return (error); 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate bp = NULL; 147*0Sstevel@tonic-gate /* 148*0Sstevel@tonic-gate * wait for CONfirm 149*0Sstevel@tonic-gate */ 150*0Sstevel@tonic-gate if ((error = tli_recv(tiptr, &bp, flag)) != 0) 151*0Sstevel@tonic-gate return (error); 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gate if (bp->b_datap->db_type != M_PROTO) { 154*0Sstevel@tonic-gate freemsg(bp); 155*0Sstevel@tonic-gate return (EPROTO); 156*0Sstevel@tonic-gate } 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate /* LINTED pointer alignment */ 159*0Sstevel@tonic-gate pptr = (union T_primitives *)bp->b_rptr; 160*0Sstevel@tonic-gate switch (pptr->type) { 161*0Sstevel@tonic-gate case T_CONN_CON: 162*0Sstevel@tonic-gate hdrsz = bp->b_wptr - bp->b_rptr; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate /* 165*0Sstevel@tonic-gate * check everything for consistency 166*0Sstevel@tonic-gate */ 167*0Sstevel@tonic-gate if (hdrsz < TCONNCONSZ || 168*0Sstevel@tonic-gate hdrsz < (pptr->conn_con.OPT_length + 169*0Sstevel@tonic-gate pptr->conn_con.OPT_offset) || 170*0Sstevel@tonic-gate hdrsz < (pptr->conn_con.RES_length + 171*0Sstevel@tonic-gate pptr->conn_con.RES_offset)) { 172*0Sstevel@tonic-gate error = EPROTO; 173*0Sstevel@tonic-gate freemsg(bp); 174*0Sstevel@tonic-gate break; 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate if (rcvcall != NULL) { 178*0Sstevel@tonic-gate /* 179*0Sstevel@tonic-gate * okay, so now we copy them 180*0Sstevel@tonic-gate */ 181*0Sstevel@tonic-gate len = MIN(pptr->conn_con.RES_length, 182*0Sstevel@tonic-gate rcvcall->addr.maxlen); 183*0Sstevel@tonic-gate bcopy(bp->b_rptr + pptr->conn_con.RES_offset, 184*0Sstevel@tonic-gate rcvcall->addr.buf, len); 185*0Sstevel@tonic-gate rcvcall->addr.len = len; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate len = MIN(pptr->conn_con.OPT_length, 188*0Sstevel@tonic-gate rcvcall->opt.maxlen); 189*0Sstevel@tonic-gate bcopy(bp->b_rptr + pptr->conn_con.OPT_offset, 190*0Sstevel@tonic-gate rcvcall->opt.buf, len); 191*0Sstevel@tonic-gate rcvcall->opt.len = len; 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate if (bp->b_cont) { 194*0Sstevel@tonic-gate nbp = bp; 195*0Sstevel@tonic-gate bp = bp->b_cont; 196*0Sstevel@tonic-gate msgsz = (int)(bp->b_wptr - bp->b_rptr); 197*0Sstevel@tonic-gate len = MIN(msgsz, rcvcall->udata.maxlen); 198*0Sstevel@tonic-gate bcopy(bp->b_rptr, rcvcall->udata.buf, len); 199*0Sstevel@tonic-gate rcvcall->udata.len = len; 200*0Sstevel@tonic-gate freemsg(nbp); 201*0Sstevel@tonic-gate } 202*0Sstevel@tonic-gate } else { 203*0Sstevel@tonic-gate freemsg(bp); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate break; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate default: 208*0Sstevel@tonic-gate error = EPROTO; 209*0Sstevel@tonic-gate freemsg(bp); 210*0Sstevel@tonic-gate break; 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate return (error); 213*0Sstevel@tonic-gate } 214