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 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 #pragma ident "%Z%%M% %I% %E% SMI" 41 42 /* 43 * Kernel TLI-like function to bind a transport endpoint 44 * to an address. 45 * 46 * Returns 0 on success or positive error code. 47 */ 48 49 #include <sys/param.h> 50 #include <sys/types.h> 51 #include <sys/proc.h> 52 #include <sys/file.h> 53 #include <sys/user.h> 54 #include <sys/errno.h> 55 #include <sys/stream.h> 56 #include <sys/strsubr.h> 57 #include <sys/ioctl.h> 58 #include <sys/stropts.h> 59 #include <sys/vnode.h> 60 #include <sys/tihdr.h> 61 #include <sys/timod.h> 62 #include <sys/tiuser.h> 63 #include <sys/t_kuser.h> 64 #include <sys/kmem.h> 65 #include <sys/sysmacros.h> 66 67 int 68 t_kbind(TIUSER *tiptr, struct t_bind *req, struct t_bind *ret) 69 { 70 struct T_bind_req *bind_req; 71 struct T_bind_ack *bind_ack; 72 int bindsz; 73 vnode_t *vp; 74 file_t *fp; 75 char *buf; 76 struct strioctl strioc; 77 int retval; 78 int error; 79 80 error = 0; 81 retval = 0; 82 fp = tiptr->fp; 83 vp = fp->f_vnode; 84 85 /* 86 * send the ioctl request and wait 87 * for a reply. 88 */ 89 bindsz = (req == NULL) ? 0 : req->addr.len; 90 bindsz = MAX(bindsz, tiptr->tp_info.addr); 91 bindsz += MAX(TBINDREQSZ, TBINDACKSZ); 92 buf = kmem_alloc(bindsz, KM_SLEEP); 93 94 /* LINTED pointer alignment */ 95 bind_req = (struct T_bind_req *)buf; 96 bind_req->PRIM_type = T_BIND_REQ; 97 bind_req->ADDR_length = (req == NULL ? 0 : req->addr.len); 98 bind_req->ADDR_offset = TBINDREQSZ; 99 bind_req->CONIND_number = (req == NULL ? 0 : req->qlen); 100 101 if (bind_req->ADDR_length) 102 bcopy(req->addr.buf, buf + bind_req->ADDR_offset, 103 bind_req->ADDR_length); 104 105 strioc.ic_cmd = TI_BIND; 106 strioc.ic_timout = 0; 107 strioc.ic_dp = buf; 108 strioc.ic_len = (int)TBINDREQSZ + bind_req->ADDR_length; 109 110 /* 111 * Usually ioctl()s are performed with the credential of the caller; 112 * in this particular case we specifically use the credential of 113 * the opener as this call is typically done in the context of a user 114 * process but on behalf of the kernel, e.g., a client connection 115 * to a server which is later shared by different users. 116 * At open time, we make sure to set fp->f_cred to kcred if such is 117 * the case. 118 */ 119 error = strdoioctl(vp->v_stream, &strioc, FNATIVE, K_TO_K, fp->f_cred, 120 &retval); 121 if (error) 122 goto badbind; 123 if (retval) { 124 if ((retval & 0xff) == TSYSERR) 125 error = (retval >> 8) & 0xff; 126 else 127 error = t_tlitosyserr(retval & 0xff); 128 goto badbind; 129 } 130 131 /* LINTED pointer alignment */ 132 bind_ack = (struct T_bind_ack *)strioc.ic_dp; 133 if (strioc.ic_len < TBINDACKSZ || bind_ack->ADDR_length == 0) { 134 error = EIO; 135 goto badbind; 136 } 137 138 /* 139 * copy bind data into users buffer 140 */ 141 if (ret) { 142 if (ret->addr.maxlen > bind_ack->ADDR_length) 143 ret->addr.len = bind_ack->ADDR_length; 144 else 145 ret->addr.len = ret->addr.maxlen; 146 147 bcopy(buf + bind_ack->ADDR_offset, ret->addr.buf, 148 ret->addr.len); 149 150 ret->qlen = bind_ack->CONIND_number; 151 } 152 153 badbind: 154 kmem_free(buf, bindsz); 155 return (error); 156 } 157