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