1 0 stevel /* 2 0 stevel * CDDL HEADER START 3 0 stevel * 4 0 stevel * The contents of this file are subject to the terms of the 5 1735 kcpoon * Common Development and Distribution License (the "License"). 6 1735 kcpoon * You may not use this file except in compliance with the License. 7 0 stevel * 8 0 stevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 0 stevel * or http://www.opensolaris.org/os/licensing. 10 0 stevel * See the License for the specific language governing permissions 11 0 stevel * and limitations under the License. 12 0 stevel * 13 0 stevel * When distributing Covered Code, include this CDDL HEADER in each 14 0 stevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 0 stevel * If applicable, add the following below this CDDL HEADER, with the 16 0 stevel * fields enclosed by brackets "[]" replaced with your own identifying 17 0 stevel * information: Portions Copyright [yyyy] [name of copyright owner] 18 0 stevel * 19 0 stevel * CDDL HEADER END 20 0 stevel */ 21 1735 kcpoon 22 0 stevel /* 23 11042 Erik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 0 stevel * Use is subject to license terms. 25 0 stevel */ 26 0 stevel 27 0 stevel #include <sys/types.h> 28 0 stevel #include <sys/systm.h> 29 0 stevel #include <sys/stream.h> 30 0 stevel #include <sys/ddi.h> 31 0 stevel #include <sys/sunddi.h> 32 0 stevel #include <sys/strsubr.h> 33 0 stevel #include <sys/strsun.h> 34 0 stevel 35 0 stevel #include <netinet/in.h> 36 0 stevel #include <netinet/ip6.h> 37 0 stevel 38 11042 Erik #include <inet/ipsec_impl.h> 39 0 stevel #include <inet/common.h> 40 0 stevel #include <inet/ip.h> 41 0 stevel #include <inet/ip6.h> 42 0 stevel #include <inet/mib2.h> 43 0 stevel #include <inet/nd.h> 44 0 stevel #include <inet/optcom.h> 45 0 stevel #include <inet/sctp_ip.h> 46 3448 dh155122 #include <inet/ipclassifier.h> 47 0 stevel #include "sctp_impl.h" 48 0 stevel 49 0 stevel void 50 0 stevel sctp_send_shutdown(sctp_t *sctp, int rexmit) 51 0 stevel { 52 0 stevel mblk_t *smp; 53 0 stevel mblk_t *sendmp; 54 0 stevel sctp_chunk_hdr_t *sch; 55 0 stevel uint32_t *ctsn; 56 0 stevel sctp_faddr_t *fp; 57 3448 dh155122 sctp_stack_t *sctps = sctp->sctp_sctps; 58 0 stevel 59 0 stevel if (sctp->sctp_state != SCTPS_ESTABLISHED && 60 0 stevel sctp->sctp_state != SCTPS_SHUTDOWN_PENDING && 61 0 stevel sctp->sctp_state != SCTPS_SHUTDOWN_SENT) { 62 0 stevel return; 63 0 stevel } 64 0 stevel 65 0 stevel if (sctp->sctp_state == SCTPS_ESTABLISHED) { 66 0 stevel sctp->sctp_state = SCTPS_SHUTDOWN_PENDING; 67 0 stevel /* 68 0 stevel * We set an upper bound on how long we will 69 0 stevel * wait for a shutdown-ack from the peer. This 70 0 stevel * is to prevent the receiver from attempting 71 0 stevel * to create a half-closed state indefinately. 72 0 stevel * See archive from IETF TSVWG mailing list 73 0 stevel * for June 2001 for more information. 74 0 stevel * Since we will not be calculating RTTs after 75 0 stevel * sending the shutdown, we can overload out_time 76 0 stevel * to track how long we have waited. 77 0 stevel */ 78 11066 rafael sctp->sctp_out_time = ddi_get_lbolt64(); 79 0 stevel } 80 0 stevel 81 0 stevel /* 82 0 stevel * If there is unsent (or unacked) data, wait for it to get ack'd 83 0 stevel */ 84 0 stevel if (sctp->sctp_xmit_head != NULL || sctp->sctp_xmit_unsent != NULL) { 85 0 stevel return; 86 0 stevel } 87 0 stevel 88 0 stevel /* rotate faddrs if we are retransmitting */ 89 0 stevel if (!rexmit) { 90 0 stevel fp = sctp->sctp_current; 91 0 stevel } else { 92 0 stevel fp = sctp_rotate_faddr(sctp, sctp->sctp_shutdown_faddr); 93 0 stevel } 94 0 stevel 95 0 stevel sctp->sctp_shutdown_faddr = fp; 96 0 stevel 97 0 stevel /* Link in a SACK if resending the shutdown */ 98 0 stevel if (sctp->sctp_state > SCTPS_SHUTDOWN_PENDING && 99 0 stevel (sendmp = sctp_make_sack(sctp, fp, NULL)) != NULL) { 100 0 stevel 101 0 stevel smp = allocb(sizeof (*sch) + sizeof (*ctsn), BPRI_MED); 102 0 stevel if (smp == NULL) { 103 0 stevel freemsg(sendmp); 104 0 stevel goto done; 105 0 stevel } 106 0 stevel linkb(sendmp, smp); 107 0 stevel 108 0 stevel sch = (sctp_chunk_hdr_t *)smp->b_rptr; 109 0 stevel smp->b_wptr = smp->b_rptr + sizeof (*sch) + sizeof (*ctsn); 110 0 stevel } else { 111 0 stevel sendmp = sctp_make_mp(sctp, fp, 112 0 stevel sizeof (*sch) + sizeof (*ctsn)); 113 0 stevel if (sendmp == NULL) { 114 3448 dh155122 SCTP_KSTAT(sctps, sctp_send_shutdown_failed); 115 0 stevel goto done; 116 0 stevel } 117 0 stevel sch = (sctp_chunk_hdr_t *)sendmp->b_wptr; 118 0 stevel sendmp->b_wptr += sizeof (*sch) + sizeof (*ctsn); 119 0 stevel 120 0 stevel /* shutdown w/o sack, update lastacked */ 121 0 stevel sctp->sctp_lastacked = sctp->sctp_ftsn - 1; 122 0 stevel } 123 0 stevel 124 0 stevel sch->sch_id = CHUNK_SHUTDOWN; 125 0 stevel sch->sch_flags = 0; 126 0 stevel sch->sch_len = htons(sizeof (*sch) + sizeof (*ctsn)); 127 0 stevel 128 0 stevel ctsn = (uint32_t *)(sch + 1); 129 0 stevel *ctsn = htonl(sctp->sctp_lastacked); 130 0 stevel 131 0 stevel /* Link the shutdown chunk in after the IP/SCTP header */ 132 0 stevel 133 0 stevel BUMP_LOCAL(sctp->sctp_obchunks); 134 0 stevel 135 0 stevel /* Send the shutdown and restart the timer */ 136 11042 Erik sctp_set_iplen(sctp, sendmp, fp->ixa); 137 11042 Erik (void) conn_ip_output(sendmp, fp->ixa); 138 11042 Erik BUMP_LOCAL(sctp->sctp_opkts); 139 0 stevel 140 0 stevel done: 141 0 stevel sctp->sctp_state = SCTPS_SHUTDOWN_SENT; 142 0 stevel SCTP_FADDR_TIMER_RESTART(sctp, sctp->sctp_current, 143 0 stevel sctp->sctp_current->rto); 144 0 stevel } 145 0 stevel 146 0 stevel int 147 1735 kcpoon sctp_shutdown_received(sctp_t *sctp, sctp_chunk_hdr_t *sch, boolean_t crwsd, 148 1735 kcpoon boolean_t rexmit, sctp_faddr_t *fp) 149 0 stevel { 150 0 stevel mblk_t *samp; 151 0 stevel sctp_chunk_hdr_t *sach; 152 0 stevel uint32_t *tsn; 153 0 stevel int trysend = 0; 154 3448 dh155122 sctp_stack_t *sctps = sctp->sctp_sctps; 155 0 stevel 156 0 stevel if (sctp->sctp_state != SCTPS_SHUTDOWN_ACK_SENT) 157 0 stevel sctp->sctp_state = SCTPS_SHUTDOWN_RECEIVED; 158 0 stevel 159 0 stevel /* Extract and process the TSN in the shutdown chunk */ 160 0 stevel if (sch != NULL) { 161 0 stevel tsn = (uint32_t *)(sch + 1); 162 0 stevel trysend = sctp_cumack(sctp, ntohl(*tsn), &samp); 163 0 stevel } 164 0 stevel 165 0 stevel /* Don't allow sending new data */ 166 4818 kcpoon if (!SCTP_IS_DETACHED(sctp) && !sctp->sctp_ulp_discon_done) { 167 8348 Eric sctp->sctp_ulp_opctl(sctp->sctp_ulpd, SOCK_OPCTL_SHUT_SEND, 0); 168 4818 kcpoon sctp->sctp_ulp_discon_done = B_TRUE; 169 4818 kcpoon } 170 0 stevel 171 0 stevel /* 172 0 stevel * If there is unsent or unacked data, try sending them out now. 173 0 stevel * The other side should acknowledge them. After we have flushed 174 0 stevel * the transmit queue, we can complete the shutdown sequence. 175 0 stevel */ 176 0 stevel if (sctp->sctp_xmit_head != NULL || sctp->sctp_xmit_unsent != NULL) 177 0 stevel return (1); 178 0 stevel 179 1735 kcpoon if (fp == NULL) { 180 1735 kcpoon /* rotate faddrs if we are retransmitting */ 181 1735 kcpoon if (!rexmit) 182 1735 kcpoon fp = sctp->sctp_current; 183 1735 kcpoon else 184 1735 kcpoon fp = sctp_rotate_faddr(sctp, sctp->sctp_shutdown_faddr); 185 1735 kcpoon } 186 1735 kcpoon sctp->sctp_shutdown_faddr = fp; 187 0 stevel 188 0 stevel samp = sctp_make_mp(sctp, fp, sizeof (*sach)); 189 1735 kcpoon if (samp == NULL) { 190 3448 dh155122 SCTP_KSTAT(sctps, sctp_send_shutdown_ack_failed); 191 0 stevel goto dotimer; 192 1735 kcpoon } 193 0 stevel 194 0 stevel sach = (sctp_chunk_hdr_t *)samp->b_wptr; 195 0 stevel sach->sch_id = CHUNK_SHUTDOWN_ACK; 196 0 stevel sach->sch_flags = 0; 197 0 stevel sach->sch_len = htons(sizeof (*sach)); 198 0 stevel 199 0 stevel samp->b_wptr += sizeof (*sach); 200 0 stevel 201 0 stevel /* 202 0 stevel * bundle a "cookie received while shutting down" error if 203 0 stevel * the caller asks for it. 204 0 stevel */ 205 0 stevel if (crwsd) { 206 0 stevel mblk_t *errmp; 207 0 stevel 208 0 stevel errmp = sctp_make_err(sctp, SCTP_ERR_COOKIE_SHUT, NULL, 0); 209 0 stevel if (errmp != NULL) { 210 0 stevel linkb(samp, errmp); 211 0 stevel BUMP_LOCAL(sctp->sctp_obchunks); 212 0 stevel } 213 0 stevel } 214 0 stevel 215 0 stevel BUMP_LOCAL(sctp->sctp_obchunks); 216 0 stevel 217 11042 Erik sctp_set_iplen(sctp, samp, fp->ixa); 218 11042 Erik (void) conn_ip_output(samp, fp->ixa); 219 11042 Erik BUMP_LOCAL(sctp->sctp_opkts); 220 0 stevel 221 0 stevel dotimer: 222 0 stevel sctp->sctp_state = SCTPS_SHUTDOWN_ACK_SENT; 223 0 stevel SCTP_FADDR_TIMER_RESTART(sctp, sctp->sctp_current, 224 0 stevel sctp->sctp_current->rto); 225 0 stevel 226 0 stevel return (trysend); 227 0 stevel } 228 0 stevel 229 0 stevel void 230 0 stevel sctp_shutdown_complete(sctp_t *sctp) 231 0 stevel { 232 0 stevel mblk_t *scmp; 233 0 stevel sctp_chunk_hdr_t *scch; 234 3448 dh155122 sctp_stack_t *sctps = sctp->sctp_sctps; 235 0 stevel 236 11042 Erik scmp = sctp_make_mp(sctp, sctp->sctp_current, sizeof (*scch)); 237 0 stevel if (scmp == NULL) { 238 0 stevel /* XXX use timer approach */ 239 3448 dh155122 SCTP_KSTAT(sctps, sctp_send_shutdown_comp_failed); 240 0 stevel return; 241 0 stevel } 242 0 stevel 243 0 stevel scch = (sctp_chunk_hdr_t *)scmp->b_wptr; 244 0 stevel scch->sch_id = CHUNK_SHUTDOWN_COMPLETE; 245 0 stevel scch->sch_flags = 0; 246 0 stevel scch->sch_len = htons(sizeof (*scch)); 247 0 stevel 248 0 stevel scmp->b_wptr += sizeof (*scch); 249 0 stevel 250 0 stevel BUMP_LOCAL(sctp->sctp_obchunks); 251 0 stevel 252 11042 Erik sctp_set_iplen(sctp, scmp, sctp->sctp_current->ixa); 253 11042 Erik (void) conn_ip_output(scmp, sctp->sctp_current->ixa); 254 11042 Erik BUMP_LOCAL(sctp->sctp_opkts); 255 0 stevel } 256 0 stevel 257 0 stevel /* 258 0 stevel * Similar to sctp_shutdown_complete(), except that since this 259 0 stevel * is out-of-the-blue, we can't use an sctp's association information, 260 0 stevel * and instead must draw all necessary info from the incoming packet. 261 0 stevel */ 262 0 stevel void 263 11042 Erik sctp_ootb_shutdown_ack(mblk_t *mp, uint_t ip_hdr_len, ip_recv_attr_t *ira, 264 11042 Erik ip_stack_t *ipst) 265 0 stevel { 266 0 stevel boolean_t isv4; 267 11042 Erik ipha_t *ipha = NULL; 268 11042 Erik ip6_t *ip6h = NULL; 269 0 stevel sctp_hdr_t *insctph; 270 0 stevel sctp_chunk_hdr_t *scch; 271 0 stevel int i; 272 0 stevel uint16_t port; 273 0 stevel mblk_t *mp1; 274 11042 Erik netstack_t *ns = ipst->ips_netstack; 275 11042 Erik sctp_stack_t *sctps = ns->netstack_sctp; 276 11042 Erik ip_xmit_attr_t ixas; 277 0 stevel 278 11042 Erik bzero(&ixas, sizeof (ixas)); 279 0 stevel 280 11042 Erik isv4 = (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION); 281 11042 Erik 282 11042 Erik ASSERT(MBLKL(mp) >= sizeof (*insctph) + sizeof (*scch) + 283 11042 Erik (isv4 ? sizeof (ipha_t) : sizeof (ip6_t))); 284 0 stevel 285 0 stevel /* 286 0 stevel * Check to see if we can reuse the incoming mblk. There should 287 11042 Erik * not be other reference. Since this packet comes from below, 288 0 stevel * there should be enough header space to fill in what the lower 289 11042 Erik * layers want to add. 290 0 stevel */ 291 11042 Erik if (DB_REF(mp) != 1) { 292 11042 Erik mp1 = allocb(MBLKL(mp) + sctps->sctps_wroff_xtra, BPRI_MED); 293 0 stevel if (mp1 == NULL) { 294 11042 Erik freeb(mp); 295 0 stevel return; 296 0 stevel } 297 3448 dh155122 mp1->b_rptr += sctps->sctps_wroff_xtra; 298 11042 Erik mp1->b_wptr = mp1->b_rptr + MBLKL(mp); 299 11042 Erik bcopy(mp->b_rptr, mp1->b_rptr, MBLKL(mp)); 300 11042 Erik freeb(mp); 301 11042 Erik mp = mp1; 302 1932 vi117747 } else { 303 11042 Erik DB_CKSUMFLAGS(mp) = 0; 304 0 stevel } 305 0 stevel 306 11042 Erik ixas.ixa_pktlen = ip_hdr_len + sizeof (*insctph) + sizeof (*scch); 307 11042 Erik ixas.ixa_ip_hdr_length = ip_hdr_len; 308 0 stevel /* 309 0 stevel * We follow the logic in tcp_xmit_early_reset() in that we skip 310 11042 Erik * reversing source route (i.e. replace all IP options with EOL). 311 0 stevel */ 312 0 stevel if (isv4) { 313 0 stevel ipaddr_t v4addr; 314 0 stevel 315 11042 Erik ipha = (ipha_t *)mp->b_rptr; 316 0 stevel for (i = IP_SIMPLE_HDR_LENGTH; i < (int)ip_hdr_len; i++) 317 11042 Erik mp->b_rptr[i] = IPOPT_EOL; 318 0 stevel /* Swap addresses */ 319 11042 Erik ipha->ipha_length = htons(ixas.ixa_pktlen); 320 11042 Erik v4addr = ipha->ipha_src; 321 11042 Erik ipha->ipha_src = ipha->ipha_dst; 322 11042 Erik ipha->ipha_dst = v4addr; 323 11042 Erik ipha->ipha_ident = 0; 324 11042 Erik ipha->ipha_ttl = (uchar_t)sctps->sctps_ipv4_ttl; 325 11042 Erik 326 11042 Erik ixas.ixa_flags = IXAF_BASIC_SIMPLE_V4; 327 0 stevel } else { 328 0 stevel in6_addr_t v6addr; 329 0 stevel 330 11042 Erik ip6h = (ip6_t *)mp->b_rptr; 331 0 stevel /* Remove any extension headers assuming partial overlay */ 332 0 stevel if (ip_hdr_len > IPV6_HDR_LEN) { 333 0 stevel uint8_t *to; 334 0 stevel 335 11042 Erik to = mp->b_rptr + ip_hdr_len - IPV6_HDR_LEN; 336 11042 Erik ovbcopy(ip6h, to, IPV6_HDR_LEN); 337 11042 Erik mp->b_rptr += ip_hdr_len - IPV6_HDR_LEN; 338 0 stevel ip_hdr_len = IPV6_HDR_LEN; 339 11042 Erik ip6h = (ip6_t *)mp->b_rptr; 340 11042 Erik ip6h->ip6_nxt = IPPROTO_SCTP; 341 0 stevel } 342 11042 Erik ip6h->ip6_plen = htons(ixas.ixa_pktlen - IPV6_HDR_LEN); 343 11042 Erik v6addr = ip6h->ip6_src; 344 11042 Erik ip6h->ip6_src = ip6h->ip6_dst; 345 11042 Erik ip6h->ip6_dst = v6addr; 346 11042 Erik ip6h->ip6_hops = (uchar_t)sctps->sctps_ipv6_hoplimit; 347 11042 Erik 348 11042 Erik ixas.ixa_flags = IXAF_BASIC_SIMPLE_V6; 349 11042 Erik if (IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_dst)) { 350 11042 Erik ixas.ixa_flags |= IXAF_SCOPEID_SET; 351 11042 Erik ixas.ixa_scopeid = ira->ira_ruifindex; 352 11042 Erik } 353 0 stevel } 354 11042 Erik 355 11042 Erik insctph = (sctp_hdr_t *)(mp->b_rptr + ip_hdr_len); 356 0 stevel 357 0 stevel /* Swap ports. Verification tag is reused. */ 358 0 stevel port = insctph->sh_sport; 359 0 stevel insctph->sh_sport = insctph->sh_dport; 360 0 stevel insctph->sh_dport = port; 361 0 stevel 362 0 stevel /* Lay in the shutdown complete chunk */ 363 0 stevel scch = (sctp_chunk_hdr_t *)(insctph + 1); 364 0 stevel scch->sch_id = CHUNK_SHUTDOWN_COMPLETE; 365 0 stevel scch->sch_len = htons(sizeof (*scch)); 366 0 stevel scch->sch_flags = 0; 367 0 stevel 368 0 stevel /* Set the T-bit */ 369 0 stevel SCTP_SET_TBIT(scch); 370 0 stevel 371 11042 Erik ixas.ixa_protocol = IPPROTO_SCTP; 372 11042 Erik ixas.ixa_zoneid = ira->ira_zoneid; 373 11042 Erik ixas.ixa_ipst = ipst; 374 11042 Erik ixas.ixa_ifindex = 0; 375 0 stevel 376 11042 Erik if (ira->ira_flags & IRAF_IPSEC_SECURE) { 377 11042 Erik /* 378 11042 Erik * Apply IPsec based on how IPsec was applied to 379 11042 Erik * the packet that was out of the blue. 380 11042 Erik */ 381 11042 Erik if (!ipsec_in_to_out(ira, &ixas, mp, ipha, ip6h)) { 382 11042 Erik BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards); 383 11042 Erik /* Note: mp already consumed and ip_drop_packet done */ 384 11042 Erik return; 385 11042 Erik } 386 11042 Erik } else { 387 11042 Erik /* 388 11042 Erik * This is in clear. The message we are building 389 11042 Erik * here should go out in clear, independent of our policy. 390 11042 Erik */ 391 11042 Erik ixas.ixa_flags |= IXAF_NO_IPSEC; 392 11042 Erik } 393 11042 Erik 394 11042 Erik (void) ip_output_simple(mp, &ixas); 395 11042 Erik ixa_cleanup(&ixas); 396 0 stevel } 397