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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Functions related to TPI. 24 */ 25 26 #include <sys/types.h> 27 #include <sys/stream.h> 28 #include <sys/strsun.h> 29 #include <sys/strsubr.h> 30 #include <sys/stropts.h> 31 #include <sys/strlog.h> 32 #define _SUN_TPI_VERSION 2 33 #include <sys/tihdr.h> 34 #include <sys/suntpi.h> 35 #include <sys/xti_inet.h> 36 #include <sys/squeue_impl.h> 37 #include <sys/squeue.h> 38 #include <sys/tsol/tnet.h> 39 40 #include <inet/common.h> 41 #include <inet/ip.h> 42 #include <inet/proto_set.h> 43 44 #include <sys/cmn_err.h> 45 46 #include "dccp_impl.h" 47 48 /* 49 * This file contains functions related to the TPI interface. 50 */ 51 52 /* 53 * XXX 54 */ 55 static void 56 dccp_copy_info(struct T_info_ack *tia, dccp_t *dccp) 57 { 58 conn_t *connp = dccp->dccp_connp; 59 dccp_stack_t *dccps = dccp->dccp_dccps; 60 extern struct T_info_ack dccp_g_t_info_ack; 61 extern struct T_info_ack dccp_g_t_info_ack_v6; 62 63 if (connp->conn_family == AF_INET6) { 64 *tia = dccp_g_t_info_ack_v6; 65 } else { 66 *tia = dccp_g_t_info_ack; 67 } 68 69 /* XXX */ 70 } 71 72 /* 73 * XXX 74 */ 75 void 76 dccp_do_capability_ack(dccp_t *dccp, struct T_capability_ack *tcap, 77 t_uscalar_t cap_bits1) 78 { 79 tcap->CAP_bits1 = 0; 80 81 if (cap_bits1 & TC1_INFO) { 82 dccp_copy_info(&tcap->INFO_ack, dccp); 83 tcap->CAP_bits1 |= TC1_INFO; 84 } 85 86 if (cap_bits1 & TC1_ACCEPTOR_ID) { 87 tcap->ACCEPTOR_id = dccp->dccp_acceptor_id; 88 tcap->CAP_bits1 |= TC1_ACCEPTOR_ID; 89 } 90 } 91 92 /* 93 * This routine responds to T_CAPABILITY_REQ messages. 94 */ 95 void 96 dccp_capability_req(dccp_t *dccp, mblk_t *mp) 97 { 98 struct T_capability_ack *tcap; 99 t_uscalar_t cap_bits1; 100 101 if (MBLKL(mp) < sizeof (struct T_capability_req)) { 102 freemsg(mp); 103 return; 104 } 105 106 cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1; 107 108 mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack), 109 mp->b_datap->db_type, T_CAPABILITY_ACK); 110 if (mp == NULL) { 111 return; 112 } 113 114 tcap = (struct T_capability_ack *)mp->b_rptr; 115 dccp_do_capability_ack(dccp, tcap, cap_bits1); 116 117 putnext(dccp->dccp_connp->conn_rq, mp); 118 } 119 120 /* 121 * Helper function to generate TPI errors acks. 122 */ 123 void 124 dccp_err_ack(dccp_t *dccp, mblk_t *mp, int t_error, int sys_error) 125 { 126 if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL) { 127 putnext(dccp->dccp_connp->conn_rq, mp); 128 } 129 } 130 131 void 132 dccp_tpi_connect(dccp_t *dccp, mblk_t *mp) 133 { 134 conn_t *connp = dccp->dccp_connp; 135 queue_t *q = connp->conn_wq; 136 struct sockaddr *sa; 137 struct T_conn_req *tcr; 138 sin_t *sin; 139 sin6_t *sin6; 140 cred_t *cr; 141 pid_t cpid; 142 socklen_t len; 143 int error; 144 145 cmn_err(CE_NOTE, "dccp_tpi.c: dccp_tpi_connect"); 146 147 cr = msg_getcred(mp, &cpid); 148 ASSERT(cr != NULL); 149 if (cr == NULL) { 150 dccp_err_ack(dccp, mp, TSYSERR, EINVAL); 151 return; 152 } 153 154 tcr = (struct T_conn_req *)mp->b_rptr; 155 156 ASSERT((uintptr_t)(mp->b_wptr - mp->b_rptr) <= (uintptr_t)INT_MAX); 157 if ((mp->b_wptr - mp->b_rptr) < sizeof (*tcr)) { 158 dccp_err_ack(dccp, mp, TPROTO, 0); 159 return; 160 } 161 162 error = proto_verify_ip_addr(connp->conn_family, sa, len); 163 if (error != 0) { 164 dccp_err_ack(dccp, mp, TSYSERR, 0); 165 return; 166 } 167 168 error = dccp_do_connect(dccp->dccp_connp, sa, len, cr, cpid); 169 if (error < 0) { 170 mp = mi_tpi_err_ack_alloc(mp, -error, 0); 171 } else if (error > 0) { 172 mp = mi_tpi_err_ack_alloc(mp, TSYSERR, error); 173 } else { 174 mp = mi_tpi_ok_ack_alloc(mp); 175 } 176 } 177 178 int 179 dccp_tpi_close(queue_t *q, int flags) 180 { 181 conn_t *connp; 182 183 ASSERT(WR(q)->q_next == NULL); 184 185 connp = Q_TO_CONN(q); 186 187 dccp_close_common(connp, flags); 188 189 qprocsoff(q); 190 inet_minor_free(connp->conn_minor_arena, connp->conn_dev); 191 192 return (0); 193 } 194 195 int 196 dccp_tpi_close_accept(queue_t *q) 197 { 198 vmem_t *minor_arena; 199 dev_t conn_dev; 200 201 cmn_err(CE_NOTE, "dccp_tpi.c: dccp_tpi_close_accept"); 202 203 return (0); 204 } 205 206 /* 207 * Options related functions. 208 */ 209 int 210 dccp_tpi_opt_get(queue_t *q, int level, int name, uchar_t *ptr) 211 { 212 return (dccp_opt_get(Q_TO_CONN(q), level, name, ptr)); 213 } 214 215 /* ARGSUSED */ 216 int 217 dccp_tpi_opt_set(queue_t *q, uint_t optset_context, int level, int name, 218 uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp, 219 void *thisdg_attrs, cred_t *cr) 220 { 221 conn_t *connp = Q_TO_CONN(q); 222 223 return (dccp_opt_set(connp, optset_context, level, name, inlen, invalp, 224 outlenp, outvalp, thisdg_attrs, cr)); 225 } 226 227 void 228 dccp_tpi_accept(queue_t *q, mblk_t *mp) 229 { 230 queue_t *rq = RD(q); 231 232 cmn_err(CE_NOTE, "dccp_tpi.c: dccp_tpi_accept"); 233 }