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 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright 2012 David Hoeppner. All rights reserved. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/stream.h> 33 #include <sys/strsun.h> 34 #include <sys/strsubr.h> 35 #include <sys/stropts.h> 36 #include <sys/strlog.h> 37 #define _SUN_TPI_VERSION 2 38 #include <sys/tihdr.h> 39 #include <sys/suntpi.h> 40 #include <sys/xti_inet.h> 41 #include <sys/squeue_impl.h> 42 #include <sys/squeue.h> 43 #include <sys/tsol/tnet.h> 44 45 #include <inet/common.h> 46 #include <inet/ip.h> 47 48 #include <sys/cmn_err.h> 49 50 #include "dccp_impl.h" 51 52 static mblk_t *dccp_conn_create_v4(conn_t *, conn_t *, mblk_t *, 53 ip_recv_attr_t *); 54 static mblk_t *dccp_conn_create_v6(conn_t *, conn_t *, mblk_t *, 55 ip_recv_attr_t *); 56 static void dccp_input_listener(void *, mblk_t *, void *, ip_recv_attr_t *); 57 58 void 59 dccp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 60 { 61 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_data"); 62 } 63 64 void 65 dccp_icmp_input(void *arg1, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 66 { 67 cmn_err(CE_NOTE, "dccp_input.c: dccp_icmp_input"); 68 } 69 70 void 71 dccp_rsrv(queue_t *q) 72 { 73 cmn_err(CE_NOTE, "dccp_input.c: dccp_rsrv"); 74 } 75 76 static mblk_t * 77 dccp_conn_create_v6(conn_t *lconnp, conn_t *connp, mblk_t *mp, 78 ip_recv_attr_t *ira) 79 { 80 return (NULL); 81 } 82 83 static mblk_t * 84 dccp_conn_create_v4(conn_t *lconnp, conn_t *connp, mblk_t *mp, 85 ip_recv_attr_t *ira) 86 { 87 dccp_t *ldccp = lconnp->conn_dccp; 88 dccp_t *dccp = connp->conn_dccp; 89 dccp_stack_t *dccps = dccp->dccp_dccps; 90 ipha_t *ipha; 91 mblk_t *tpi_mp; 92 sin_t sin; 93 94 ASSERT(ira->ira_flags & IRAF_IS_IPV4); 95 ipha = (ipha_t *)mp->b_rptr; 96 97 connp->conn_ipversion = IPV4_VERSION; 98 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &connp->conn_laddr_v6); 99 IN6_IPADDR_TO_V4MAPPED(ipha->ipha_src, &connp->conn_faddr_v6); 100 connp->conn_saddr_v6 = connp->conn_laddr_v6; 101 102 sin = sin_null; 103 sin.sin_addr.s_addr = connp->conn_faddr_v4; 104 sin.sin_port = connp->conn_fport; 105 sin.sin_family = AF_INET; 106 107 if (lconnp->conn_recv_ancillary.crb_recvdstaddr) { 108 cmn_err(CE_NOTE, "ancillary"); 109 110 sin_t sind; 111 112 sind = sin_null; 113 sind.sin_addr.s_addr = connp->conn_laddr_v4; 114 sind.sin_port = connp->conn_lport; 115 sind.sin_family = AF_INET; 116 117 tpi_mp = mi_tpi_extconn_ind(NULL, 118 (char *)&sind, sizeof (sin_t), (char *)&dccp, 119 (t_scalar_t)sizeof (intptr_t), (char *)&sind, 120 sizeof (sin_t), (t_scalar_t) 1); /* XXX */ 121 122 } else { 123 tpi_mp = mi_tpi_conn_ind(NULL, 124 (char *)&sin, sizeof (sin_t), 125 (char *)&dccp, (t_scalar_t)sizeof (intptr_t), 126 (t_scalar_t) 1); /* XXX */ 127 } 128 129 return (tpi_mp); 130 } 131 132 static void 133 dccp_input_listener(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) 134 { 135 conn_t *lconnp = (conn_t *)arg; 136 conn_t *econnp; 137 dccp_t *listener = lconnp->conn_dccp; 138 dccp_t *eager; 139 dccp_stack_t *dccps = listener->dccp_dccps; 140 ip_stack_t *ipst = dccps->dccps_netstack->netstack_ip; 141 dccpha_t *dccpha; 142 squeue_t *new_sqp; 143 mblk_t *tpi_mp; 144 mblk_t *mp1; 145 uint_t ip_hdr_len; 146 uint_t type; 147 int error; 148 149 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener"); 150 151 ip_hdr_len = ira->ira_ip_hdr_length; 152 dccpha = (dccpha_t *)&mp->b_rptr[ip_hdr_len]; 153 type = (uint_t)dccpha->dha_type; 154 155 if (type != DCCP_PKT_REQUEST) { 156 cmn_err(CE_NOTE, "not request pkt"); 157 158 /* XXX do something with a reset packet sent? */ 159 freemsg(mp); 160 return; 161 } 162 163 /* XXX memory pressure */ 164 165 /* XXX request defense */ 166 167 /* XXX number of connections per listener */ 168 169 ASSERT(ira->ira_sqp != NULL); 170 new_sqp = ira->ira_sqp; 171 172 econnp = (conn_t *)dccp_get_conn(arg2, dccps); 173 if (econnp == NULL) { 174 cmn_err(CE_NOTE, "econnp not found (eager)"); 175 goto error2; 176 } 177 178 ASSERT(econnp->conn_netstack == lconnp->conn_netstack); 179 econnp->conn_sqp = new_sqp; 180 econnp->conn_initial_sqp = new_sqp; 181 econnp->conn_ixa->ixa_sqp = new_sqp; 182 183 econnp->conn_fport = dccpha->dha_lport; 184 econnp->conn_lport = dccpha->dha_fport; 185 186 error = conn_inherit_parent(lconnp, econnp); 187 if (error != 0) { 188 cmn_err(CE_NOTE, "conn_inherit_parent failed"); 189 goto error3; 190 } 191 192 econnp->conn_ixa->ixa_src_generation = ipst->ips_src_generation; 193 194 195 ASSERT(OK_32PTR(mp->b_rptr)); 196 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION || 197 IPH_HDR_VERSION(mp->b_rptr) == IPV6_VERSION); 198 199 if (lconnp->conn_family == AF_INET) { 200 ASSERT(IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION); 201 tpi_mp = dccp_conn_create_v4(lconnp, econnp, mp, ira); 202 } else { 203 tpi_mp = dccp_conn_create_v6(lconnp, econnp, mp, ira); 204 } 205 206 if (tpi_mp == NULL) { 207 cmn_err(CE_NOTE, "tpi_mo == NULL"); 208 goto error3; 209 } 210 211 eager = econnp->conn_dccp; 212 SOCK_CONNID_INIT(eager->dccp_connid); 213 214 dccp_init_values(eager, listener); 215 216 ASSERT((econnp->conn_ixa->ixa_flags & 217 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE | 218 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)) == 219 (IXAF_SET_ULP_CKSUM | IXAF_VERIFY_SOURCE | 220 IXAF_VERIFY_PMTU | IXAF_VERIFY_LSO)); 221 222 if (ira->ira_cred != NULL) { 223 mblk_setcred(tpi_mp, ira->ira_cred, ira->ira_cpid); 224 } 225 226 if (IPCL_IS_NONSTR(lconnp)) { 227 econnp->conn_flags |= IPCL_NONSTR; 228 } 229 230 /* XXX dccps is right? */ 231 dccp_bind_hash_insert(&dccps->dccps_bind_fanout[ 232 DCCP_BIND_HASH(econnp->conn_lport, dccps->dccps_bind_fanout_size)], eager, 0); 233 234 SOCK_CONNID_BUMP(eager->dccp_connid); 235 236 error = dccp_set_destination(eager); 237 if (error != 0) { 238 cmn_err(CE_NOTE, "dccp_set_destination failed."); 239 dccp_bind_hash_remove(eager); 240 goto error3; 241 } 242 243 CONN_INC_REF(lconnp); 244 245 /* 246 mp1 = dccp_xmit_mp(eager, eager->dccp_xmit_head, 0, 247 NULL, NULL, 0, B_FALSE, NULL, B_FALSE); 248 */ 249 mp1 = dccp_generate_packet(lconnp, mp); 250 if (mp1 == NULL) { 251 cmn_err(CE_NOTE, "dccp_xmit_mp failed"); 252 253 CONN_INC_REF(econnp); 254 goto error; 255 } 256 257 CONN_INC_REF(econnp); 258 259 error = ipcl_conn_insert(econnp); 260 if (error != 0) { 261 cmn_err(CE_NOTE, "ipcl_conn_insert(econnp) failed"); 262 goto error; 263 } 264 265 freemsg(mp); 266 267 if (econnp->conn_sqp == lconnp->conn_sqp) { 268 (void) conn_ip_output(mp1, econnp->conn_ixa); 269 CONN_DEC_REF(econnp); 270 } else { 271 SQUEUE_ENTER_ONE(econnp->conn_sqp, mp1, dccp_send_synack, 272 econnp, NULL, SQ_PROCESS, SQTAG_TCP_SEND_SYNACK); /* XXX */ 273 } 274 275 return; 276 error: 277 error2: 278 error3: 279 freemsg(mp); 280 } 281 282 void 283 dccp_input_listener_unbound(void *arg, mblk_t *mp, void *arg2, 284 ip_recv_attr_t *ira) 285 { 286 conn_t *connp = (conn_t *)arg; 287 squeue_t *sqp = (squeue_t *)arg2; 288 squeue_t *new_sqp; 289 uint32_t conn_flags; 290 291 cmn_err(CE_NOTE, "dccp_input.c: dccp_input_listener_unbound"); 292 293 ASSERT(ira->ira_sqp != NULL); 294 new_sqp = ira->ira_sqp; 295 296 if (connp->conn_fanout == NULL) { 297 goto done; 298 } 299 300 /* 301 * Bind to correct squeue. 302 */ 303 if (!(connp->conn_flags & IPCL_FULLY_BOUND)) { 304 cmn_err(CE_NOTE, "not fully bound"); 305 306 mutex_enter(&connp->conn_fanout->connf_lock); 307 mutex_enter(&connp->conn_lock); 308 309 if (connp->conn_ref != 4 || 310 connp->conn_dccp->dccp_state != DCCPS_LISTEN) { 311 mutex_exit(&connp->conn_lock); 312 mutex_exit(&connp->conn_fanout->connf_lock); 313 goto done; 314 } 315 316 if (connp->conn_sqp != new_sqp) { 317 while (connp->conn_sqp != new_sqp) { 318 (void) casptr(&connp->conn_sqp, sqp, new_sqp); 319 } 320 connp->conn_ixa->ixa_sqp = new_sqp; 321 } 322 323 do { 324 conn_flags = connp->conn_flags; 325 conn_flags |= IPCL_FULLY_BOUND; 326 (void) cas32(&connp->conn_flags, connp->conn_flags, 327 conn_flags); 328 } while (!(connp->conn_flags & IPCL_FULLY_BOUND)); 329 330 mutex_exit(&connp->conn_lock); 331 mutex_exit(&connp->conn_fanout->connf_lock); 332 333 connp->conn_recv = dccp_input_listener; 334 } 335 336 done: 337 if (connp->conn_sqp != sqp) { 338 CONN_INC_REF(connp); 339 SQUEUE_ENTER_ONE(connp->conn_sqp, mp, connp->conn_recv, connp, 340 ira, SQ_FILL, SQTAG_DCCP_CONN_REQ_UNBOUND); 341 } else { 342 dccp_input_listener(connp, mp, sqp, ira); 343 } 344 } 345 346 boolean_t 347 dccp_verifyicmp(conn_t *connp, void *arg2, icmph_t *icmph, icmp6_t *icmp6, 348 ip_recv_attr_t *ira) 349 { 350 cmn_err(CE_NOTE, "dccp_input.c: dccp_verifyicmp"); 351 352 return (B_TRUE); 353 }