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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/systm.h> 29 #include <sys/stream.h> 30 #include <sys/cmn_err.h> 31 #include <sys/ddi.h> 32 #include <sys/strsubr.h> 33 #include <sys/tsol/tnet.h> 34 35 #include <netinet/in.h> 36 #include <netinet/ip6.h> 37 38 #include <inet/common.h> 39 #include <inet/ip.h> 40 #include <inet/ip6.h> 41 #include <inet/mib2.h> 42 #include <inet/sctp_ip.h> 43 #include <inet/ipclassifier.h> 44 #include <inet/ip_ire.h> 45 #include "sctp_impl.h" 46 #include "sctp_asconf.h" 47 48 ssize_t 49 sctp_link_abort(mblk_t *mp, uint16_t serror, char *details, size_t len, 50 int iserror, boolean_t tbit) 51 { 52 size_t alen; 53 mblk_t *amp; 54 sctp_chunk_hdr_t *acp; 55 sctp_parm_hdr_t *eph; 56 57 ASSERT(mp != NULL && mp->b_cont == NULL); 58 59 alen = sizeof (*acp) + (serror != 0 ? (sizeof (*eph) + len) : 0); 60 61 amp = allocb(alen, BPRI_MED); 62 if (amp == NULL) { 63 return (-1); 64 } 65 66 amp->b_wptr = amp->b_rptr + alen; 67 68 /* Chunk header */ 69 acp = (sctp_chunk_hdr_t *)amp->b_rptr; 70 acp->sch_id = iserror ? CHUNK_ERROR : CHUNK_ABORT; 71 acp->sch_flags = 0; 72 acp->sch_len = htons(alen); 73 if (tbit) 74 SCTP_SET_TBIT(acp); 75 76 linkb(mp, amp); 77 78 if (serror == 0) { 79 return (alen); 80 } 81 82 eph = (sctp_parm_hdr_t *)(acp + 1); 83 eph->sph_type = htons(serror); 84 eph->sph_len = htons(len + sizeof (*eph)); 85 86 if (len > 0) { 87 bcopy(details, eph + 1, len); 88 } 89 90 /* XXX pad */ 91 92 return (alen); 93 } 94 95 void 96 sctp_user_abort(sctp_t *sctp, mblk_t *data) 97 { 98 mblk_t *mp; 99 int len, hdrlen; 100 char *cause; 101 sctp_faddr_t *fp = sctp->sctp_current; 102 sctp_stack_t *sctps = sctp->sctp_sctps; 103 104 /* 105 * Don't need notification if connection is not yet setup, 106 * call sctp_clean_death() to reclaim resources. 107 * Any pending connect call(s) will error out. 108 */ 109 if (sctp->sctp_state < SCTPS_COOKIE_WAIT) { 110 sctp_clean_death(sctp, ECONNABORTED); 111 return; 112 } 113 114 mp = sctp_make_mp(sctp, fp, 0); 115 if (mp == NULL) { 116 SCTP_KSTAT(sctps, sctp_send_user_abort_failed); 117 return; 118 } 119 120 /* 121 * Create abort chunk. 122 */ 123 if (data) { 124 if (fp->isv4) { 125 hdrlen = sctp->sctp_hdr_len; 126 } else { 127 hdrlen = sctp->sctp_hdr6_len; 128 } 129 hdrlen += sizeof (sctp_chunk_hdr_t) + sizeof (sctp_parm_hdr_t); 130 cause = (char *)data->b_rptr; 131 len = data->b_wptr - data->b_rptr; 132 133 if (len + hdrlen > fp->sfa_pmss) { 134 len = fp->sfa_pmss - hdrlen; 135 } 136 } else { 137 cause = NULL; 138 len = 0; 139 } 140 /* 141 * Since it is a user abort, we should have the sctp_t and hence 142 * the correct verification tag. So we should not set the T-bit 143 * in the ABORT. 144 */ 145 if ((len = sctp_link_abort(mp, SCTP_ERR_USER_ABORT, cause, len, 0, 146 B_FALSE)) < 0) { 147 freemsg(mp); 148 return; 149 } 150 sctp_set_iplen(sctp, mp); 151 BUMP_MIB(&sctps->sctps_mib, sctpAborted); 152 BUMP_LOCAL(sctp->sctp_opkts); 153 BUMP_LOCAL(sctp->sctp_obchunks); 154 155 CONN_INC_REF(sctp->sctp_connp); 156 mp->b_flag |= MSGHASREF; 157 IP_PUT(mp, sctp->sctp_connp, fp->isv4); 158 159 sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL); 160 sctp_clean_death(sctp, ECONNABORTED); 161 } 162 163 /* 164 * If iserror == 0, sends an abort. If iserror != 0, sends an error. 165 */ 166 void 167 sctp_send_abort(sctp_t *sctp, uint32_t vtag, uint16_t serror, char *details, 168 size_t len, mblk_t *inmp, int iserror, boolean_t tbit) 169 { 170 171 mblk_t *hmp; 172 uint32_t ip_hdr_len; 173 ipha_t *iniph; 174 ipha_t *ahiph; 175 ip6_t *inip6h; 176 ip6_t *ahip6h; 177 sctp_hdr_t *sh; 178 sctp_hdr_t *insh; 179 size_t ahlen; 180 uchar_t *p; 181 ssize_t alen; 182 int isv4; 183 ire_t *ire; 184 irb_t *irb; 185 ts_label_t *tsl; 186 conn_t *connp; 187 cred_t *cr = NULL; 188 pid_t pid; 189 sctp_stack_t *sctps = sctp->sctp_sctps; 190 ip_stack_t *ipst; 191 192 isv4 = (IPH_HDR_VERSION(inmp->b_rptr) == IPV4_VERSION); 193 if (isv4) { 194 ahlen = sctp->sctp_hdr_len; 195 } else { 196 ahlen = sctp->sctp_hdr6_len; 197 } 198 199 /* 200 * If this is a labeled system, then check to see if we're allowed to 201 * send a response to this particular sender. If not, then just drop. 202 */ 203 if (is_system_labeled() && !tsol_can_reply_error(inmp)) 204 return; 205 206 hmp = allocb_cred(sctps->sctps_wroff_xtra + ahlen, 207 CONN_CRED(sctp->sctp_connp), sctp->sctp_cpid); 208 if (hmp == NULL) { 209 /* XXX no resources */ 210 return; 211 } 212 213 /* copy in the IP / SCTP header */ 214 p = hmp->b_rptr + sctps->sctps_wroff_xtra; 215 hmp->b_rptr = p; 216 hmp->b_wptr = p + ahlen; 217 if (isv4) { 218 bcopy(sctp->sctp_iphc, p, sctp->sctp_hdr_len); 219 /* 220 * Composite is likely incomplete at this point, so pull 221 * info from the incoming IP / SCTP headers. 222 */ 223 ahiph = (ipha_t *)p; 224 iniph = (ipha_t *)inmp->b_rptr; 225 ip_hdr_len = IPH_HDR_LENGTH(inmp->b_rptr); 226 227 sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr_len); 228 ASSERT(OK_32PTR(sh)); 229 230 insh = (sctp_hdr_t *)((uchar_t *)iniph + ip_hdr_len); 231 ASSERT(OK_32PTR(insh)); 232 233 /* Copy in the peer's IP addr */ 234 ahiph->ipha_dst = iniph->ipha_src; 235 ahiph->ipha_src = iniph->ipha_dst; 236 } else { 237 bcopy(sctp->sctp_iphc6, p, sctp->sctp_hdr6_len); 238 ahip6h = (ip6_t *)p; 239 inip6h = (ip6_t *)inmp->b_rptr; 240 ip_hdr_len = ip_hdr_length_v6(inmp, inip6h); 241 242 sh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr6_len); 243 ASSERT(OK_32PTR(sh)); 244 245 insh = (sctp_hdr_t *)((uchar_t *)inip6h + ip_hdr_len); 246 ASSERT(OK_32PTR(insh)); 247 248 /* Copy in the peer's IP addr */ 249 ahip6h->ip6_dst = inip6h->ip6_src; 250 ahip6h->ip6_src = inip6h->ip6_dst; 251 } 252 253 /* Fill in the holes in the SCTP common header */ 254 sh->sh_sport = insh->sh_dport; 255 sh->sh_dport = insh->sh_sport; 256 sh->sh_verf = vtag; 257 258 /* Link in the abort chunk */ 259 if ((alen = sctp_link_abort(hmp, serror, details, len, iserror, tbit)) 260 < 0) { 261 freemsg(hmp); 262 return; 263 } 264 265 if (isv4) { 266 ahiph->ipha_length = htons(ahlen + alen); 267 } else { 268 ahip6h->ip6_plen = htons(alen + sizeof (*sh)); 269 } 270 271 BUMP_MIB(&sctps->sctps_mib, sctpAborted); 272 BUMP_LOCAL(sctp->sctp_obchunks); 273 274 ipst = sctps->sctps_netstack->netstack_ip; 275 connp = sctp->sctp_connp; 276 if (is_system_labeled() && (cr = msg_getcred(inmp, &pid)) != NULL && 277 crgetlabel(cr) != NULL) { 278 int err; 279 boolean_t exempt = connp->conn_mac_exempt; 280 281 if (isv4) 282 err = tsol_check_label(cr, &hmp, exempt, ipst, pid); 283 else 284 err = tsol_check_label_v6(cr, &hmp, exempt, ipst, pid); 285 if (err != 0) { 286 freemsg(hmp); 287 return; 288 } 289 } 290 291 /* Stash the conn ptr info. for IP */ 292 SCTP_STASH_IPINFO(hmp, NULL); 293 294 CONN_INC_REF(connp); 295 hmp->b_flag |= MSGHASREF; 296 IP_PUT(hmp, connp, sctp->sctp_current == NULL ? B_TRUE : 297 sctp->sctp_current->isv4); 298 /* 299 * Let's just mark the IRE for this destination as temporary 300 * to prevent any DoS attack. 301 */ 302 tsl = cr == NULL ? NULL : crgetlabel(cr); 303 if (isv4) { 304 ire = ire_cache_lookup(iniph->ipha_src, sctp->sctp_zoneid, tsl, 305 ipst); 306 } else { 307 ire = ire_cache_lookup_v6(&inip6h->ip6_src, sctp->sctp_zoneid, 308 tsl, ipst); 309 } 310 /* 311 * In the normal case the ire would be non-null, however it could be 312 * null, say, if IP needs to resolve the gateway for this address. We 313 * only care about IRE_CACHE. 314 */ 315 if (ire == NULL) 316 return; 317 if (ire->ire_type != IRE_CACHE) { 318 ire_refrele(ire); 319 return; 320 } 321 irb = ire->ire_bucket; 322 /* ire_lock is not needed, as ire_marks is protected by irb_lock */ 323 rw_enter(&irb->irb_lock, RW_WRITER); 324 /* 325 * Only increment the temporary IRE count if the original 326 * IRE is not already marked temporary. 327 */ 328 if (!(ire->ire_marks & IRE_MARK_TEMPORARY)) { 329 irb->irb_tmp_ire_cnt++; 330 ire->ire_marks |= IRE_MARK_TEMPORARY; 331 } 332 rw_exit(&irb->irb_lock); 333 ire_refrele(ire); 334 } 335 336 /*ARGSUSED*/ 337 mblk_t * 338 sctp_make_err(sctp_t *sctp, uint16_t serror, void *details, size_t len) 339 { 340 341 mblk_t *emp; 342 size_t elen; 343 sctp_chunk_hdr_t *ecp; 344 sctp_parm_hdr_t *eph; 345 int pad; 346 347 if ((pad = len % SCTP_ALIGN) != 0) { 348 pad = SCTP_ALIGN - pad; 349 } 350 351 elen = sizeof (*ecp) + sizeof (*eph) + len; 352 emp = allocb(elen + pad, BPRI_MED); 353 if (emp == NULL) { 354 return (NULL); 355 } 356 357 emp->b_wptr = emp->b_rptr + elen + pad; 358 359 /* Chunk header */ 360 ecp = (sctp_chunk_hdr_t *)emp->b_rptr; 361 ecp->sch_id = CHUNK_ERROR; 362 ecp->sch_flags = 0; 363 ecp->sch_len = htons(elen); 364 365 eph = (sctp_parm_hdr_t *)(ecp + 1); 366 eph->sph_type = htons(serror); 367 eph->sph_len = htons(len + sizeof (*eph)); 368 369 if (len > 0) { 370 bcopy(details, eph + 1, len); 371 } 372 373 if (pad != 0) { 374 bzero((uchar_t *)(eph + 1) + len, pad); 375 } 376 377 return (emp); 378 } 379 380 /* 381 * Called from sctp_input_data() to add one error chunk to the error 382 * chunks list. The error chunks list will be processed at the end 383 * of sctp_input_data() by calling sctp_process_err(). 384 */ 385 void 386 sctp_add_err(sctp_t *sctp, uint16_t serror, void *details, size_t len, 387 sctp_faddr_t *dest) 388 { 389 sctp_stack_t *sctps = sctp->sctp_sctps; 390 mblk_t *emp; 391 uint32_t emp_len; 392 uint32_t mss; 393 mblk_t *sendmp; 394 sctp_faddr_t *fp; 395 396 emp = sctp_make_err(sctp, serror, details, len); 397 if (emp == NULL) 398 return; 399 emp_len = MBLKL(emp); 400 if (sctp->sctp_err_chunks != NULL) { 401 fp = SCTP_CHUNK_DEST(sctp->sctp_err_chunks); 402 } else { 403 fp = dest; 404 SCTP_SET_CHUNK_DEST(emp, dest); 405 } 406 mss = fp->sfa_pmss; 407 408 /* 409 * If the current output packet cannot include the new error chunk, 410 * send out the current packet and then add the new error chunk 411 * to the new output packet. 412 */ 413 if (sctp->sctp_err_len + emp_len > mss) { 414 if ((sendmp = sctp_make_mp(sctp, fp, 0)) == NULL) { 415 SCTP_KSTAT(sctps, sctp_send_err_failed); 416 /* Just free the latest error chunk. */ 417 freeb(emp); 418 return; 419 } 420 sendmp->b_cont = sctp->sctp_err_chunks; 421 sctp_set_iplen(sctp, sendmp); 422 sctp_add_sendq(sctp, sendmp); 423 424 sctp->sctp_err_chunks = emp; 425 sctp->sctp_err_len = emp_len; 426 SCTP_SET_CHUNK_DEST(emp, dest); 427 } else { 428 if (sctp->sctp_err_chunks != NULL) 429 linkb(sctp->sctp_err_chunks, emp); 430 else 431 sctp->sctp_err_chunks = emp; 432 sctp->sctp_err_len += emp_len; 433 } 434 /* Assume that we will send it out... */ 435 BUMP_LOCAL(sctp->sctp_obchunks); 436 } 437 438 /* 439 * Called from sctp_input_data() to send out error chunks created during 440 * the processing of all the chunks in an incoming packet. 441 */ 442 void 443 sctp_process_err(sctp_t *sctp) 444 { 445 sctp_stack_t *sctps = sctp->sctp_sctps; 446 mblk_t *errmp; 447 mblk_t *sendmp; 448 449 ASSERT(sctp->sctp_err_chunks != NULL); 450 errmp = sctp->sctp_err_chunks; 451 if ((sendmp = sctp_make_mp(sctp, SCTP_CHUNK_DEST(errmp), 0)) == NULL) { 452 SCTP_KSTAT(sctps, sctp_send_err_failed); 453 freemsg(errmp); 454 goto done; 455 } 456 sendmp->b_cont = errmp; 457 sctp_set_iplen(sctp, sendmp); 458 sctp_add_sendq(sctp, sendmp); 459 done: 460 sctp->sctp_err_chunks = NULL; 461 sctp->sctp_err_len = 0; 462 } 463 464 /* 465 * Returns 0 on non-fatal error, otherwise a system error on fatal 466 * error. 467 */ 468 int 469 sctp_handle_error(sctp_t *sctp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ch, 470 mblk_t *mp) 471 { 472 sctp_parm_hdr_t *errh; 473 sctp_chunk_hdr_t *uch; 474 475 if (ch->sch_len == htons(sizeof (*ch))) { 476 /* no error cause given */ 477 return (0); 478 } 479 errh = (sctp_parm_hdr_t *)(ch + 1); 480 sctp_error_event(sctp, ch); 481 482 switch (errh->sph_type) { 483 /* 484 * Both BAD_SID and NO_USR_DATA errors 485 * indicate a serious bug in our stack, 486 * so complain and abort the association. 487 */ 488 case SCTP_ERR_BAD_SID: 489 cmn_err(CE_WARN, "BUG! send to invalid SID"); 490 sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0); 491 return (ECONNABORTED); 492 case SCTP_ERR_NO_USR_DATA: 493 cmn_err(CE_WARN, "BUG! no usr data"); 494 sctp_send_abort(sctp, sctph->sh_verf, 0, NULL, 0, mp, 0, 0); 495 return (ECONNABORTED); 496 case SCTP_ERR_UNREC_CHUNK: 497 /* Pull out the unrecognized chunk type */ 498 if (ntohs(errh->sph_len) < (sizeof (*errh) + sizeof (*uch))) { 499 /* Not enough to process */ 500 return (0); 501 } 502 uch = (sctp_chunk_hdr_t *)(errh + 1); 503 if (uch->sch_id == CHUNK_ASCONF) { 504 /* Turn on ASCONF sending */ 505 sctp->sctp_understands_asconf = B_FALSE; 506 /* 507 * Hand off to asconf to clear out the unacked 508 * asconf chunk. 509 */ 510 if (ntohs(uch->sch_len) != 511 (ntohs(errh->sph_len) - sizeof (*errh))) { 512 /* malformed */ 513 dprint(0, ("Malformed Unrec Chunk error\n")); 514 return (0); 515 } 516 sctp_asconf_free_cxmit(sctp, uch); 517 return (0); 518 } 519 /* Else drop it */ 520 break; 521 default: 522 break; 523 } 524 525 return (0); 526 } 527