1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/systm.h> 31*0Sstevel@tonic-gate #include <sys/stream.h> 32*0Sstevel@tonic-gate #include <sys/ddi.h> 33*0Sstevel@tonic-gate #include <sys/sunddi.h> 34*0Sstevel@tonic-gate #include <sys/kmem.h> 35*0Sstevel@tonic-gate #include <sys/socket.h> 36*0Sstevel@tonic-gate #include <sys/random.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include <netinet/in.h> 39*0Sstevel@tonic-gate #include <netinet/ip6.h> 40*0Sstevel@tonic-gate #include <netinet/sctp.h> 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate #include <inet/common.h> 43*0Sstevel@tonic-gate #include <inet/ip.h> 44*0Sstevel@tonic-gate #include <inet/ip6.h> 45*0Sstevel@tonic-gate #include <inet/ip_ire.h> 46*0Sstevel@tonic-gate #include <inet/mi.h> 47*0Sstevel@tonic-gate #include <inet/mib2.h> 48*0Sstevel@tonic-gate #include <inet/nd.h> 49*0Sstevel@tonic-gate #include <inet/optcom.h> 50*0Sstevel@tonic-gate #include <inet/sctp_ip.h> 51*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 52*0Sstevel@tonic-gate #include "sctp_impl.h" 53*0Sstevel@tonic-gate #include "sctp_addr.h" 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate static struct kmem_cache *sctp_kmem_faddr_cache; 56*0Sstevel@tonic-gate static void sctp_init_faddr(sctp_t *, sctp_faddr_t *, in6_addr_t *); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate /* Set the source address. Refer to comments in sctp_ire2faddr(). */ 59*0Sstevel@tonic-gate static void 60*0Sstevel@tonic-gate set_saddr(sctp_t *sctp, sctp_faddr_t *fp, boolean_t v6) 61*0Sstevel@tonic-gate { 62*0Sstevel@tonic-gate if (sctp->sctp_bound_to_all) { 63*0Sstevel@tonic-gate V6_SET_ZERO(fp->saddr); 64*0Sstevel@tonic-gate } else { 65*0Sstevel@tonic-gate fp->saddr = sctp_get_valid_addr(sctp, v6); 66*0Sstevel@tonic-gate if (!v6 && IN6_IS_ADDR_V4MAPPED_ANY(&fp->saddr) || 67*0Sstevel@tonic-gate v6 && IN6_IS_ADDR_UNSPECIFIED(&fp->saddr)) { 68*0Sstevel@tonic-gate fp->state = SCTP_FADDRS_UNREACH; 69*0Sstevel@tonic-gate /* Disable heartbeat. */ 70*0Sstevel@tonic-gate fp->hb_expiry = 0; 71*0Sstevel@tonic-gate fp->hb_pending = B_FALSE; 72*0Sstevel@tonic-gate fp->strikes = 0; 73*0Sstevel@tonic-gate } 74*0Sstevel@tonic-gate } 75*0Sstevel@tonic-gate } 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate /* 78*0Sstevel@tonic-gate * Call this function to update the cached IRE of a peer addr fp. 79*0Sstevel@tonic-gate */ 80*0Sstevel@tonic-gate void 81*0Sstevel@tonic-gate sctp_ire2faddr(sctp_t *sctp, sctp_faddr_t *fp) 82*0Sstevel@tonic-gate { 83*0Sstevel@tonic-gate ire_t *ire; 84*0Sstevel@tonic-gate ipaddr_t addr4; 85*0Sstevel@tonic-gate in6_addr_t laddr; 86*0Sstevel@tonic-gate sctp_saddr_ipif_t *sp; 87*0Sstevel@tonic-gate uint_t ipif_seqid; 88*0Sstevel@tonic-gate int hdrlen; 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate /* Remove the previous cache IRE */ 91*0Sstevel@tonic-gate if ((ire = fp->ire) != NULL) { 92*0Sstevel@tonic-gate IRE_REFRELE_NOTR(ire); 93*0Sstevel@tonic-gate fp->ire = NULL; 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate /* 97*0Sstevel@tonic-gate * If this addr is not reachable, mark it as unconfirmed for now, the 98*0Sstevel@tonic-gate * state will be changed back to unreachable later in this function 99*0Sstevel@tonic-gate * if it is still the case. 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate if (fp->state == SCTP_FADDRS_UNREACH) { 102*0Sstevel@tonic-gate fp->state = SCTP_FADDRS_UNCONFIRMED; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate if (fp->isv4) { 106*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->faddr, addr4); 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate ire = ire_cache_lookup(addr4, sctp->sctp_zoneid); 109*0Sstevel@tonic-gate if (ire == NULL) { 110*0Sstevel@tonic-gate dprint(3, ("ire2faddr: no ire for %x:%x:%x:%x\n", 111*0Sstevel@tonic-gate SCTP_PRINTADDR(fp->faddr))); 112*0Sstevel@tonic-gate /* 113*0Sstevel@tonic-gate * It is tempting to just leave the src addr 114*0Sstevel@tonic-gate * unspecified and let IP figure it out, but we 115*0Sstevel@tonic-gate * *cannot* do this, since IP may choose a src addr 116*0Sstevel@tonic-gate * that is not part of this association... unless 117*0Sstevel@tonic-gate * this sctp has bound to all addrs. So if the ire 118*0Sstevel@tonic-gate * lookup fails, try to find one in our src addr 119*0Sstevel@tonic-gate * list, unless the sctp has bound to all addrs, in 120*0Sstevel@tonic-gate * which case we change the src addr to unspec. 121*0Sstevel@tonic-gate * 122*0Sstevel@tonic-gate * Note that if this is a v6 endpoint but it does 123*0Sstevel@tonic-gate * not have any v4 address at this point (e.g. may 124*0Sstevel@tonic-gate * have been deleted), sctp_get_valid_addr() will 125*0Sstevel@tonic-gate * return mapped INADDR_ANY. In this case, this 126*0Sstevel@tonic-gate * address should be marked not reachable so that 127*0Sstevel@tonic-gate * it won't be used to send data. 128*0Sstevel@tonic-gate */ 129*0Sstevel@tonic-gate set_saddr(sctp, fp, B_FALSE); 130*0Sstevel@tonic-gate goto set_current; 131*0Sstevel@tonic-gate } 132*0Sstevel@tonic-gate ipif_seqid = ire->ire_ipif->ipif_seqid; 133*0Sstevel@tonic-gate dprint(2, ("ire2faddr: got ire for %x:%x:%x:%x, ", 134*0Sstevel@tonic-gate SCTP_PRINTADDR(fp->faddr))); 135*0Sstevel@tonic-gate dprint(2, ("src = %x\n", ire->ire_src_addr)); 136*0Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(ire->ire_src_addr, &laddr); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate /* make sure the laddr is part of this association */ 139*0Sstevel@tonic-gate if ((sp = sctp_ipif_lookup(sctp, ipif_seqid)) != 140*0Sstevel@tonic-gate NULL && !sp->saddr_ipif_dontsrc) { 141*0Sstevel@tonic-gate fp->saddr = laddr; 142*0Sstevel@tonic-gate } else { 143*0Sstevel@tonic-gate ip2dbg(("ire2faddr: src addr is not part of assc\n")); 144*0Sstevel@tonic-gate set_saddr(sctp, fp, B_FALSE); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate } else { 147*0Sstevel@tonic-gate ire = ire_cache_lookup_v6(&fp->faddr, sctp->sctp_zoneid); 148*0Sstevel@tonic-gate if (ire == NULL) { 149*0Sstevel@tonic-gate dprint(3, ("ire2faddr: no ire for %x:%x:%x:%x\n", 150*0Sstevel@tonic-gate SCTP_PRINTADDR(fp->faddr))); 151*0Sstevel@tonic-gate set_saddr(sctp, fp, B_TRUE); 152*0Sstevel@tonic-gate goto set_current; 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate ipif_seqid = ire->ire_ipif->ipif_seqid; 155*0Sstevel@tonic-gate dprint(2, ("ire2faddr: got ire for %x:%x:%x:%x, ", 156*0Sstevel@tonic-gate SCTP_PRINTADDR(fp->faddr))); 157*0Sstevel@tonic-gate dprint(2, ("src=%x:%x:%x:%x\n", 158*0Sstevel@tonic-gate SCTP_PRINTADDR(ire->ire_src_addr_v6))); 159*0Sstevel@tonic-gate laddr = ire->ire_src_addr_v6; 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate /* make sure the laddr is part of this association */ 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate if ((sp = sctp_ipif_lookup(sctp, ipif_seqid)) != 164*0Sstevel@tonic-gate NULL && !sp->saddr_ipif_dontsrc) { 165*0Sstevel@tonic-gate fp->saddr = laddr; 166*0Sstevel@tonic-gate } else { 167*0Sstevel@tonic-gate dprint(2, ("ire2faddr: src addr is not part " 168*0Sstevel@tonic-gate "of assc\n")); 169*0Sstevel@tonic-gate set_saddr(sctp, fp, B_TRUE); 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* Cache the IRE */ 174*0Sstevel@tonic-gate IRE_REFHOLD_NOTR(ire); 175*0Sstevel@tonic-gate fp->ire = ire; 176*0Sstevel@tonic-gate if (fp->ire->ire_type == IRE_LOOPBACK && !sctp->sctp_loopback) 177*0Sstevel@tonic-gate sctp->sctp_loopback = 1; 178*0Sstevel@tonic-gate IRE_REFRELE(ire); 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* 181*0Sstevel@tonic-gate * Pull out RTO information for this faddr and use it if we don't 182*0Sstevel@tonic-gate * have any yet. 183*0Sstevel@tonic-gate */ 184*0Sstevel@tonic-gate if (fp->srtt == -1 && ire->ire_uinfo.iulp_rtt != 0) { 185*0Sstevel@tonic-gate fp->srtt = ire->ire_uinfo.iulp_rtt; 186*0Sstevel@tonic-gate fp->rttvar = ire->ire_uinfo.iulp_rtt_sd; 187*0Sstevel@tonic-gate fp->rto = 3 * fp->srtt; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate /* Bound the RTO by configured min and max values */ 190*0Sstevel@tonic-gate if (fp->rto < sctp->sctp_rto_min) { 191*0Sstevel@tonic-gate fp->rto = sctp->sctp_rto_min; 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate if (fp->rto > sctp->sctp_rto_max) { 194*0Sstevel@tonic-gate fp->rto = sctp->sctp_rto_max; 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate /* 199*0Sstevel@tonic-gate * Record the MTU for this faddr. If the MTU for this faddr has 200*0Sstevel@tonic-gate * changed, check if the assc MTU will also change. 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate if (fp->isv4) { 203*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len; 204*0Sstevel@tonic-gate } else { 205*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate if ((fp->sfa_pmss + hdrlen) != ire->ire_max_frag) { 208*0Sstevel@tonic-gate /* Make sure that sfa_pmss is a multiple of SCTP_ALIGN. */ 209*0Sstevel@tonic-gate fp->sfa_pmss = (ire->ire_max_frag - hdrlen) & ~(SCTP_ALIGN - 1); 210*0Sstevel@tonic-gate if (fp->cwnd < (fp->sfa_pmss * 2)) { 211*0Sstevel@tonic-gate fp->cwnd = fp->sfa_pmss * sctp_slow_start_initial; 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate } 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate set_current: 216*0Sstevel@tonic-gate if (fp == sctp->sctp_current) { 217*0Sstevel@tonic-gate sctp_faddr2hdraddr(fp, sctp); 218*0Sstevel@tonic-gate sctp->sctp_mss = fp->sfa_pmss; 219*0Sstevel@tonic-gate if (!SCTP_IS_DETACHED(sctp)) { 220*0Sstevel@tonic-gate sctp_set_ulp_prop(sctp); 221*0Sstevel@tonic-gate } 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /*ARGSUSED*/ 226*0Sstevel@tonic-gate void 227*0Sstevel@tonic-gate sctp_faddr2ire(sctp_t *sctp, sctp_faddr_t *fp) 228*0Sstevel@tonic-gate { 229*0Sstevel@tonic-gate ire_t *ire; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate if ((ire = fp->ire) == NULL) { 232*0Sstevel@tonic-gate return; 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate mutex_enter(&ire->ire_lock); 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate /* If the cached IRE is going sway, there is no point to update it. */ 238*0Sstevel@tonic-gate if (ire->ire_marks & IRE_MARK_CONDEMNED) { 239*0Sstevel@tonic-gate mutex_exit(&ire->ire_lock); 240*0Sstevel@tonic-gate IRE_REFRELE_NOTR(ire); 241*0Sstevel@tonic-gate fp->ire = NULL; 242*0Sstevel@tonic-gate return; 243*0Sstevel@tonic-gate } 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate /* 246*0Sstevel@tonic-gate * Only record the PMTU for this faddr if we actually have 247*0Sstevel@tonic-gate * done discovery. This prevents initialized default from 248*0Sstevel@tonic-gate * clobbering any real info that IP may have. 249*0Sstevel@tonic-gate */ 250*0Sstevel@tonic-gate if (fp->pmtu_discovered) { 251*0Sstevel@tonic-gate if (fp->isv4) { 252*0Sstevel@tonic-gate ire->ire_max_frag = fp->sfa_pmss + sctp->sctp_hdr_len; 253*0Sstevel@tonic-gate } else { 254*0Sstevel@tonic-gate ire->ire_max_frag = fp->sfa_pmss + sctp->sctp_hdr6_len; 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate 258*0Sstevel@tonic-gate if (fp->rtt_updates >= sctp_rtt_updates) { 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * If there is no old cached values, initialize them 261*0Sstevel@tonic-gate * conservatively. Set them to be (1.5 * new value). 262*0Sstevel@tonic-gate * This code copied from ip_ire_advise(). 263*0Sstevel@tonic-gate */ 264*0Sstevel@tonic-gate if (ire->ire_uinfo.iulp_rtt != 0) { 265*0Sstevel@tonic-gate ire->ire_uinfo.iulp_rtt = (ire->ire_uinfo.iulp_rtt + 266*0Sstevel@tonic-gate fp->srtt) >> 1; 267*0Sstevel@tonic-gate } else { 268*0Sstevel@tonic-gate ire->ire_uinfo.iulp_rtt = fp->srtt + 269*0Sstevel@tonic-gate (fp->srtt >> 1); 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate if (ire->ire_uinfo.iulp_rtt_sd != 0) { 272*0Sstevel@tonic-gate ire->ire_uinfo.iulp_rtt_sd = 273*0Sstevel@tonic-gate (ire->ire_uinfo.iulp_rtt_sd + 274*0Sstevel@tonic-gate fp->rttvar) >> 1; 275*0Sstevel@tonic-gate } else { 276*0Sstevel@tonic-gate ire->ire_uinfo.iulp_rtt_sd = fp->rttvar + 277*0Sstevel@tonic-gate (fp->rttvar >> 1); 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate fp->rtt_updates = 0; 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate mutex_exit(&ire->ire_lock); 283*0Sstevel@tonic-gate } 284*0Sstevel@tonic-gate 285*0Sstevel@tonic-gate /* 286*0Sstevel@tonic-gate * The sender must set the total length in the IP header. 287*0Sstevel@tonic-gate * If sendto == NULL, the current will be used. 288*0Sstevel@tonic-gate */ 289*0Sstevel@tonic-gate mblk_t * 290*0Sstevel@tonic-gate sctp_make_mp(sctp_t *sctp, sctp_faddr_t *sendto, int trailer) 291*0Sstevel@tonic-gate { 292*0Sstevel@tonic-gate mblk_t *mp; 293*0Sstevel@tonic-gate size_t ipsctplen; 294*0Sstevel@tonic-gate int isv4; 295*0Sstevel@tonic-gate sctp_faddr_t *fp; 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate ASSERT(sctp->sctp_current != NULL || sendto != NULL); 298*0Sstevel@tonic-gate if (sendto == NULL) { 299*0Sstevel@tonic-gate fp = sctp->sctp_current; 300*0Sstevel@tonic-gate } else { 301*0Sstevel@tonic-gate fp = sendto; 302*0Sstevel@tonic-gate } 303*0Sstevel@tonic-gate isv4 = fp->isv4; 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate /* Try to look for another IRE again. */ 306*0Sstevel@tonic-gate if (fp->ire == NULL) 307*0Sstevel@tonic-gate sctp_ire2faddr(sctp, fp); 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate /* There is no suitable source address to use, return. */ 310*0Sstevel@tonic-gate if (fp->state == SCTP_FADDRS_UNREACH) 311*0Sstevel@tonic-gate return (NULL); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate if (isv4) { 314*0Sstevel@tonic-gate ipsctplen = sctp->sctp_hdr_len; 315*0Sstevel@tonic-gate } else { 316*0Sstevel@tonic-gate ipsctplen = sctp->sctp_hdr6_len; 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate mp = allocb(ipsctplen + sctp_wroff_xtra + trailer, BPRI_MED); 320*0Sstevel@tonic-gate if (mp == NULL) { 321*0Sstevel@tonic-gate ip1dbg(("sctp_make_mp: error makign mp..\n")); 322*0Sstevel@tonic-gate return (NULL); 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate mp->b_rptr += sctp_wroff_xtra; 325*0Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + ipsctplen; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate ASSERT(OK_32PTR(mp->b_wptr)); 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate if (isv4) { 330*0Sstevel@tonic-gate ipha_t *iph = (ipha_t *)mp->b_rptr; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate bcopy(sctp->sctp_iphc, mp->b_rptr, ipsctplen); 333*0Sstevel@tonic-gate if (fp != sctp->sctp_current) { 334*0Sstevel@tonic-gate /* fiddle with the dst addr */ 335*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->faddr, iph->ipha_dst); 336*0Sstevel@tonic-gate /* fix up src addr */ 337*0Sstevel@tonic-gate if (!IN6_IS_ADDR_V4MAPPED_ANY(&fp->saddr)) { 338*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->saddr, 339*0Sstevel@tonic-gate iph->ipha_src); 340*0Sstevel@tonic-gate } else if (sctp->sctp_bound_to_all) { 341*0Sstevel@tonic-gate iph->ipha_src = INADDR_ANY; 342*0Sstevel@tonic-gate } 343*0Sstevel@tonic-gate } 344*0Sstevel@tonic-gate /* set or clear the don't fragment bit */ 345*0Sstevel@tonic-gate if (fp->df) { 346*0Sstevel@tonic-gate iph->ipha_fragment_offset_and_flags = htons(IPH_DF); 347*0Sstevel@tonic-gate } else { 348*0Sstevel@tonic-gate iph->ipha_fragment_offset_and_flags = 0; 349*0Sstevel@tonic-gate } 350*0Sstevel@tonic-gate } else { 351*0Sstevel@tonic-gate bcopy(sctp->sctp_iphc6, mp->b_rptr, ipsctplen); 352*0Sstevel@tonic-gate if (fp != sctp->sctp_current) { 353*0Sstevel@tonic-gate /* fiddle with the dst addr */ 354*0Sstevel@tonic-gate ((ip6_t *)(mp->b_rptr))->ip6_dst = fp->faddr; 355*0Sstevel@tonic-gate /* fix up src addr */ 356*0Sstevel@tonic-gate if (!IN6_IS_ADDR_UNSPECIFIED(&fp->saddr)) { 357*0Sstevel@tonic-gate ((ip6_t *)(mp->b_rptr))->ip6_src = fp->saddr; 358*0Sstevel@tonic-gate } else if (sctp->sctp_bound_to_all) { 359*0Sstevel@tonic-gate bzero(&((ip6_t *)(mp->b_rptr))->ip6_src, 360*0Sstevel@tonic-gate sizeof (in6_addr_t)); 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate ASSERT(sctp->sctp_connp != NULL); 365*0Sstevel@tonic-gate 366*0Sstevel@tonic-gate /* 367*0Sstevel@tonic-gate * IP will not free this IRE if it is condemned. SCTP needs to 368*0Sstevel@tonic-gate * free it. 369*0Sstevel@tonic-gate */ 370*0Sstevel@tonic-gate if ((fp->ire != NULL) && (fp->ire->ire_marks & IRE_MARK_CONDEMNED)) { 371*0Sstevel@tonic-gate IRE_REFRELE_NOTR(fp->ire); 372*0Sstevel@tonic-gate fp->ire = NULL; 373*0Sstevel@tonic-gate } 374*0Sstevel@tonic-gate /* Stash the conn and ire ptr info. for IP */ 375*0Sstevel@tonic-gate SCTP_STASH_IPINFO(mp, fp->ire); 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate return (mp); 378*0Sstevel@tonic-gate } 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate /* 381*0Sstevel@tonic-gate * Notify upper layers about preferred write offset, write size. 382*0Sstevel@tonic-gate */ 383*0Sstevel@tonic-gate void 384*0Sstevel@tonic-gate sctp_set_ulp_prop(sctp_t *sctp) 385*0Sstevel@tonic-gate { 386*0Sstevel@tonic-gate int hdrlen; 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate if (sctp->sctp_current->isv4) { 389*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len; 390*0Sstevel@tonic-gate } else { 391*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate ASSERT(sctp->sctp_ulpd); 394*0Sstevel@tonic-gate 395*0Sstevel@tonic-gate ASSERT(sctp->sctp_current->sfa_pmss == sctp->sctp_mss); 396*0Sstevel@tonic-gate sctp->sctp_ulp_prop(sctp->sctp_ulpd, 397*0Sstevel@tonic-gate sctp_wroff_xtra + hdrlen + sizeof (sctp_data_hdr_t), 398*0Sstevel@tonic-gate sctp->sctp_mss - sizeof (sctp_data_hdr_t)); 399*0Sstevel@tonic-gate } 400*0Sstevel@tonic-gate 401*0Sstevel@tonic-gate void 402*0Sstevel@tonic-gate sctp_set_iplen(sctp_t *sctp, mblk_t *mp) 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate uint16_t sum = 0; 405*0Sstevel@tonic-gate ipha_t *iph; 406*0Sstevel@tonic-gate ip6_t *ip6h; 407*0Sstevel@tonic-gate mblk_t *pmp = mp; 408*0Sstevel@tonic-gate boolean_t isv4; 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate isv4 = (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION); 411*0Sstevel@tonic-gate for (; pmp; pmp = pmp->b_cont) 412*0Sstevel@tonic-gate sum += pmp->b_wptr - pmp->b_rptr; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate if (isv4) { 415*0Sstevel@tonic-gate iph = (ipha_t *)mp->b_rptr; 416*0Sstevel@tonic-gate iph->ipha_length = htons(sum); 417*0Sstevel@tonic-gate } else { 418*0Sstevel@tonic-gate ip6h = (ip6_t *)mp->b_rptr; 419*0Sstevel@tonic-gate ip6h->ip6_plen = htons(sum - ((char *)&sctp->sctp_ip6h[1] - 420*0Sstevel@tonic-gate sctp->sctp_iphc6)); 421*0Sstevel@tonic-gate } 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate int 425*0Sstevel@tonic-gate sctp_compare_faddrsets(sctp_faddr_t *a1, sctp_faddr_t *a2) 426*0Sstevel@tonic-gate { 427*0Sstevel@tonic-gate int na1 = 0; 428*0Sstevel@tonic-gate int overlap = 0; 429*0Sstevel@tonic-gate int equal = 1; 430*0Sstevel@tonic-gate int onematch; 431*0Sstevel@tonic-gate sctp_faddr_t *fp1, *fp2; 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate for (fp1 = a1; fp1; fp1 = fp1->next) { 434*0Sstevel@tonic-gate onematch = 0; 435*0Sstevel@tonic-gate for (fp2 = a2; fp2; fp2 = fp2->next) { 436*0Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&fp1->faddr, &fp2->faddr)) { 437*0Sstevel@tonic-gate overlap++; 438*0Sstevel@tonic-gate onematch = 1; 439*0Sstevel@tonic-gate break; 440*0Sstevel@tonic-gate } 441*0Sstevel@tonic-gate if (!onematch) { 442*0Sstevel@tonic-gate equal = 0; 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate } 445*0Sstevel@tonic-gate na1++; 446*0Sstevel@tonic-gate } 447*0Sstevel@tonic-gate 448*0Sstevel@tonic-gate if (equal) { 449*0Sstevel@tonic-gate return (SCTP_ADDR_EQUAL); 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate if (overlap == na1) { 452*0Sstevel@tonic-gate return (SCTP_ADDR_SUBSET); 453*0Sstevel@tonic-gate } 454*0Sstevel@tonic-gate if (overlap) { 455*0Sstevel@tonic-gate return (SCTP_ADDR_OVERLAP); 456*0Sstevel@tonic-gate } 457*0Sstevel@tonic-gate return (SCTP_ADDR_DISJOINT); 458*0Sstevel@tonic-gate } 459*0Sstevel@tonic-gate 460*0Sstevel@tonic-gate /* 461*0Sstevel@tonic-gate * Returns 0 on success, -1 on memory allocation failure. If sleep 462*0Sstevel@tonic-gate * is true, should never fail. 463*0Sstevel@tonic-gate * Caller must hold conn fanout lock. 464*0Sstevel@tonic-gate */ 465*0Sstevel@tonic-gate int 466*0Sstevel@tonic-gate sctp_add_faddr(sctp_t *sctp, in6_addr_t *addr, int sleep) 467*0Sstevel@tonic-gate { 468*0Sstevel@tonic-gate sctp_faddr_t *faddr; 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate dprint(4, ("add_faddr: %x:%x:%x:%x %d\n", SCTP_PRINTADDR(*addr), 471*0Sstevel@tonic-gate sleep)); 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate if ((faddr = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep)) == NULL) { 474*0Sstevel@tonic-gate return (-1); 475*0Sstevel@tonic-gate } 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate sctp_init_faddr(sctp, faddr, addr); 478*0Sstevel@tonic-gate ASSERT(faddr->next == NULL); 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* tack it on to the end */ 481*0Sstevel@tonic-gate if (sctp->sctp_lastfaddr != NULL) { 482*0Sstevel@tonic-gate sctp->sctp_lastfaddr->next = faddr; 483*0Sstevel@tonic-gate } else { 484*0Sstevel@tonic-gate /* list is empty */ 485*0Sstevel@tonic-gate ASSERT(sctp->sctp_faddrs == NULL); 486*0Sstevel@tonic-gate sctp->sctp_faddrs = faddr; 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate sctp->sctp_lastfaddr = faddr; 489*0Sstevel@tonic-gate 490*0Sstevel@tonic-gate return (0); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate /* 494*0Sstevel@tonic-gate * Caller must hold conn fanout lock. 495*0Sstevel@tonic-gate */ 496*0Sstevel@tonic-gate int 497*0Sstevel@tonic-gate sctp_add_faddr_first(sctp_t *sctp, in6_addr_t *addr, int sleep) 498*0Sstevel@tonic-gate { 499*0Sstevel@tonic-gate sctp_faddr_t *faddr; 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate dprint(4, ("add_faddr_first: %x:%x:%x:%x %d\n", SCTP_PRINTADDR(*addr), 502*0Sstevel@tonic-gate sleep)); 503*0Sstevel@tonic-gate 504*0Sstevel@tonic-gate if ((faddr = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep)) == NULL) { 505*0Sstevel@tonic-gate return (-1); 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate sctp_init_faddr(sctp, faddr, addr); 508*0Sstevel@tonic-gate ASSERT(faddr->next == NULL); 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate /* Put it at the beginning of the list */ 511*0Sstevel@tonic-gate if (sctp->sctp_faddrs != NULL) { 512*0Sstevel@tonic-gate faddr->next = sctp->sctp_faddrs; 513*0Sstevel@tonic-gate } else { 514*0Sstevel@tonic-gate sctp->sctp_lastfaddr = faddr; 515*0Sstevel@tonic-gate } 516*0Sstevel@tonic-gate sctp->sctp_faddrs = faddr; 517*0Sstevel@tonic-gate 518*0Sstevel@tonic-gate return (0); 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate sctp_faddr_t * 522*0Sstevel@tonic-gate sctp_lookup_faddr(sctp_t *sctp, in6_addr_t *addr) 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate sctp_faddr_t *fp; 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 527*0Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&fp->faddr, addr)) 528*0Sstevel@tonic-gate break; 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate return (fp); 532*0Sstevel@tonic-gate } 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate sctp_faddr_t * 535*0Sstevel@tonic-gate sctp_lookup_faddr_nosctp(sctp_faddr_t *fp, in6_addr_t *addr) 536*0Sstevel@tonic-gate { 537*0Sstevel@tonic-gate for (; fp; fp = fp->next) { 538*0Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&fp->faddr, addr)) { 539*0Sstevel@tonic-gate break; 540*0Sstevel@tonic-gate } 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate return (fp); 544*0Sstevel@tonic-gate } 545*0Sstevel@tonic-gate 546*0Sstevel@tonic-gate void 547*0Sstevel@tonic-gate sctp_faddr2hdraddr(sctp_faddr_t *fp, sctp_t *sctp) 548*0Sstevel@tonic-gate { 549*0Sstevel@tonic-gate if (fp->isv4) { 550*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->faddr, 551*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_dst); 552*0Sstevel@tonic-gate /* Must not allow unspec src addr if not bound to all */ 553*0Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED_ANY(&fp->saddr) && 554*0Sstevel@tonic-gate !sctp->sctp_bound_to_all) { 555*0Sstevel@tonic-gate /* 556*0Sstevel@tonic-gate * set the src to the first v4 saddr and hope 557*0Sstevel@tonic-gate * for the best 558*0Sstevel@tonic-gate */ 559*0Sstevel@tonic-gate fp->saddr = sctp_get_valid_addr(sctp, B_FALSE); 560*0Sstevel@tonic-gate } 561*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->saddr, sctp->sctp_ipha->ipha_src); 562*0Sstevel@tonic-gate /* update don't fragment bit */ 563*0Sstevel@tonic-gate if (fp->df) { 564*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_fragment_offset_and_flags = 565*0Sstevel@tonic-gate htons(IPH_DF); 566*0Sstevel@tonic-gate } else { 567*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_fragment_offset_and_flags = 0; 568*0Sstevel@tonic-gate } 569*0Sstevel@tonic-gate } else { 570*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_dst = fp->faddr; 571*0Sstevel@tonic-gate /* Must not allow unspec src addr if not bound to all */ 572*0Sstevel@tonic-gate if (IN6_IS_ADDR_UNSPECIFIED(&fp->saddr) && 573*0Sstevel@tonic-gate !sctp->sctp_bound_to_all) { 574*0Sstevel@tonic-gate /* 575*0Sstevel@tonic-gate * set the src to the first v6 saddr and hope 576*0Sstevel@tonic-gate * for the best 577*0Sstevel@tonic-gate */ 578*0Sstevel@tonic-gate fp->saddr = sctp_get_valid_addr(sctp, B_TRUE); 579*0Sstevel@tonic-gate } 580*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_src = fp->saddr; 581*0Sstevel@tonic-gate } 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate void 585*0Sstevel@tonic-gate sctp_redo_faddr_srcs(sctp_t *sctp) 586*0Sstevel@tonic-gate { 587*0Sstevel@tonic-gate sctp_faddr_t *fp; 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 590*0Sstevel@tonic-gate sctp_ire2faddr(sctp, fp); 591*0Sstevel@tonic-gate } 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate sctp_faddr2hdraddr(sctp->sctp_current, sctp); 594*0Sstevel@tonic-gate } 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate void 597*0Sstevel@tonic-gate sctp_faddr_alive(sctp_t *sctp, sctp_faddr_t *fp) 598*0Sstevel@tonic-gate { 599*0Sstevel@tonic-gate int64_t now = lbolt64; 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate fp->strikes = 0; 602*0Sstevel@tonic-gate sctp->sctp_strikes = 0; 603*0Sstevel@tonic-gate fp->lastactive = now; 604*0Sstevel@tonic-gate fp->hb_expiry = now + SET_HB_INTVL(fp); 605*0Sstevel@tonic-gate fp->hb_pending = B_FALSE; 606*0Sstevel@tonic-gate if (fp->state != SCTP_FADDRS_ALIVE) { 607*0Sstevel@tonic-gate fp->state = SCTP_FADDRS_ALIVE; 608*0Sstevel@tonic-gate sctp_intf_event(sctp, fp->faddr, SCTP_ADDR_AVAILABLE, 0); 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate /* If this is the primary, switch back to it now */ 611*0Sstevel@tonic-gate if (fp == sctp->sctp_primary) { 612*0Sstevel@tonic-gate sctp->sctp_current = fp; 613*0Sstevel@tonic-gate sctp->sctp_mss = fp->sfa_pmss; 614*0Sstevel@tonic-gate /* Reset the addrs in the composite header */ 615*0Sstevel@tonic-gate sctp_faddr2hdraddr(fp, sctp); 616*0Sstevel@tonic-gate if (!SCTP_IS_DETACHED(sctp)) { 617*0Sstevel@tonic-gate sctp_set_ulp_prop(sctp); 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate } 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate if (fp->ire == NULL) { 622*0Sstevel@tonic-gate /* Should have a full IRE now */ 623*0Sstevel@tonic-gate sctp_ire2faddr(sctp, fp); 624*0Sstevel@tonic-gate } 625*0Sstevel@tonic-gate } 626*0Sstevel@tonic-gate 627*0Sstevel@tonic-gate int 628*0Sstevel@tonic-gate sctp_is_a_faddr_clean(sctp_t *sctp) 629*0Sstevel@tonic-gate { 630*0Sstevel@tonic-gate sctp_faddr_t *fp; 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 633*0Sstevel@tonic-gate if (fp->state == SCTP_FADDRS_ALIVE && fp->strikes == 0) { 634*0Sstevel@tonic-gate return (1); 635*0Sstevel@tonic-gate } 636*0Sstevel@tonic-gate } 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate return (0); 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate /* 642*0Sstevel@tonic-gate * Returns 0 if there is at leave one other active faddr, -1 if there 643*0Sstevel@tonic-gate * are none. If there are none left, faddr_dead() will start killing the 644*0Sstevel@tonic-gate * association. 645*0Sstevel@tonic-gate * If the downed faddr was the current faddr, a new current faddr 646*0Sstevel@tonic-gate * will be chosen. 647*0Sstevel@tonic-gate */ 648*0Sstevel@tonic-gate int 649*0Sstevel@tonic-gate sctp_faddr_dead(sctp_t *sctp, sctp_faddr_t *fp, int newstate) 650*0Sstevel@tonic-gate { 651*0Sstevel@tonic-gate sctp_faddr_t *ofp; 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate if (fp->state == SCTP_FADDRS_ALIVE) { 654*0Sstevel@tonic-gate sctp_intf_event(sctp, fp->faddr, SCTP_ADDR_UNREACHABLE, 0); 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate fp->state = newstate; 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate dprint(1, ("sctp_faddr_dead: %x:%x:%x:%x down (state=%d)\n", 659*0Sstevel@tonic-gate SCTP_PRINTADDR(fp->faddr), newstate)); 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate if (fp == sctp->sctp_current) { 662*0Sstevel@tonic-gate /* Current faddr down; need to switch it */ 663*0Sstevel@tonic-gate sctp->sctp_current = NULL; 664*0Sstevel@tonic-gate } 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate /* Find next alive faddr */ 667*0Sstevel@tonic-gate ofp = fp; 668*0Sstevel@tonic-gate for (fp = fp->next; fp; fp = fp->next) { 669*0Sstevel@tonic-gate if (fp->state == SCTP_FADDRS_ALIVE) { 670*0Sstevel@tonic-gate break; 671*0Sstevel@tonic-gate } 672*0Sstevel@tonic-gate } 673*0Sstevel@tonic-gate 674*0Sstevel@tonic-gate if (fp == NULL) { 675*0Sstevel@tonic-gate /* Continue from beginning of list */ 676*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp != ofp; fp = fp->next) { 677*0Sstevel@tonic-gate if (fp->state == SCTP_FADDRS_ALIVE) { 678*0Sstevel@tonic-gate break; 679*0Sstevel@tonic-gate } 680*0Sstevel@tonic-gate } 681*0Sstevel@tonic-gate } 682*0Sstevel@tonic-gate 683*0Sstevel@tonic-gate if (fp != ofp) { 684*0Sstevel@tonic-gate if (sctp->sctp_current == NULL) { 685*0Sstevel@tonic-gate dprint(1, ("sctp_faddr_dead: failover->%x:%x:%x:%x\n", 686*0Sstevel@tonic-gate SCTP_PRINTADDR(fp->faddr))); 687*0Sstevel@tonic-gate sctp->sctp_current = fp; 688*0Sstevel@tonic-gate sctp->sctp_mss = fp->sfa_pmss; 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate /* Reset the addrs in the composite header */ 691*0Sstevel@tonic-gate sctp_faddr2hdraddr(fp, sctp); 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate if (!SCTP_IS_DETACHED(sctp)) { 694*0Sstevel@tonic-gate sctp_set_ulp_prop(sctp); 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate } 697*0Sstevel@tonic-gate return (0); 698*0Sstevel@tonic-gate } 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate /* All faddrs are down; kill the association */ 702*0Sstevel@tonic-gate dprint(1, ("sctp_faddr_dead: all faddrs down, killing assoc\n")); 703*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 704*0Sstevel@tonic-gate sctp_assoc_event(sctp, sctp->sctp_state < SCTPS_ESTABLISHED ? 705*0Sstevel@tonic-gate SCTP_CANT_STR_ASSOC : SCTP_COMM_LOST, 0, NULL); 706*0Sstevel@tonic-gate sctp_clean_death(sctp, sctp->sctp_client_errno ? 707*0Sstevel@tonic-gate sctp->sctp_client_errno : ETIMEDOUT); 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate return (-1); 710*0Sstevel@tonic-gate } 711*0Sstevel@tonic-gate 712*0Sstevel@tonic-gate sctp_faddr_t * 713*0Sstevel@tonic-gate sctp_rotate_faddr(sctp_t *sctp, sctp_faddr_t *ofp) 714*0Sstevel@tonic-gate { 715*0Sstevel@tonic-gate sctp_faddr_t *nfp = NULL; 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate if (ofp == NULL) { 718*0Sstevel@tonic-gate ofp = sctp->sctp_current; 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate /* Find the next live one */ 722*0Sstevel@tonic-gate for (nfp = ofp->next; nfp != NULL; nfp = nfp->next) { 723*0Sstevel@tonic-gate if (nfp->state == SCTP_FADDRS_ALIVE) { 724*0Sstevel@tonic-gate break; 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate } 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate if (nfp == NULL) { 729*0Sstevel@tonic-gate /* Continue from beginning of list */ 730*0Sstevel@tonic-gate for (nfp = sctp->sctp_faddrs; nfp != ofp; nfp = nfp->next) { 731*0Sstevel@tonic-gate if (nfp->state == SCTP_FADDRS_ALIVE) { 732*0Sstevel@tonic-gate break; 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate } 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate 737*0Sstevel@tonic-gate /* 738*0Sstevel@tonic-gate * nfp could only be NULL if all faddrs are down, and when 739*0Sstevel@tonic-gate * this happens, faddr_dead() should have killed the 740*0Sstevel@tonic-gate * association. Hence this assertion... 741*0Sstevel@tonic-gate */ 742*0Sstevel@tonic-gate ASSERT(nfp != NULL); 743*0Sstevel@tonic-gate return (nfp); 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate void 747*0Sstevel@tonic-gate sctp_unlink_faddr(sctp_t *sctp, sctp_faddr_t *fp) 748*0Sstevel@tonic-gate { 749*0Sstevel@tonic-gate sctp_faddr_t *fpp; 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate if (!sctp->sctp_faddrs) { 752*0Sstevel@tonic-gate return; 753*0Sstevel@tonic-gate } 754*0Sstevel@tonic-gate 755*0Sstevel@tonic-gate if (fp->timer_mp != NULL) { 756*0Sstevel@tonic-gate sctp_timer_free(fp->timer_mp); 757*0Sstevel@tonic-gate fp->timer_mp = NULL; 758*0Sstevel@tonic-gate fp->timer_running = 0; 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate if (fp->rc_timer_mp != NULL) { 761*0Sstevel@tonic-gate sctp_timer_free(fp->rc_timer_mp); 762*0Sstevel@tonic-gate fp->rc_timer_mp = NULL; 763*0Sstevel@tonic-gate fp->rc_timer_running = 0; 764*0Sstevel@tonic-gate } 765*0Sstevel@tonic-gate if (fp->ire != NULL) { 766*0Sstevel@tonic-gate IRE_REFRELE_NOTR(fp->ire); 767*0Sstevel@tonic-gate fp->ire = NULL; 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate if (fp == sctp->sctp_faddrs) { 771*0Sstevel@tonic-gate goto gotit; 772*0Sstevel@tonic-gate } 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate for (fpp = sctp->sctp_faddrs; fpp->next != fp; fpp = fpp->next) 775*0Sstevel@tonic-gate ; 776*0Sstevel@tonic-gate 777*0Sstevel@tonic-gate gotit: 778*0Sstevel@tonic-gate ASSERT(sctp->sctp_conn_tfp != NULL); 779*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 780*0Sstevel@tonic-gate if (fp == sctp->sctp_faddrs) { 781*0Sstevel@tonic-gate sctp->sctp_faddrs = fp->next; 782*0Sstevel@tonic-gate } else { 783*0Sstevel@tonic-gate fpp->next = fp->next; 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 786*0Sstevel@tonic-gate /* XXX faddr2ire? */ 787*0Sstevel@tonic-gate kmem_cache_free(sctp_kmem_faddr_cache, fp); 788*0Sstevel@tonic-gate } 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate void 791*0Sstevel@tonic-gate sctp_zap_faddrs(sctp_t *sctp, int caller_holds_lock) 792*0Sstevel@tonic-gate { 793*0Sstevel@tonic-gate sctp_faddr_t *fp, *fpn; 794*0Sstevel@tonic-gate 795*0Sstevel@tonic-gate if (sctp->sctp_faddrs == NULL) { 796*0Sstevel@tonic-gate ASSERT(sctp->sctp_lastfaddr == NULL); 797*0Sstevel@tonic-gate return; 798*0Sstevel@tonic-gate } 799*0Sstevel@tonic-gate 800*0Sstevel@tonic-gate ASSERT(sctp->sctp_lastfaddr != NULL); 801*0Sstevel@tonic-gate sctp->sctp_lastfaddr = NULL; 802*0Sstevel@tonic-gate sctp->sctp_current = NULL; 803*0Sstevel@tonic-gate sctp->sctp_primary = NULL; 804*0Sstevel@tonic-gate 805*0Sstevel@tonic-gate sctp_free_faddr_timers(sctp); 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate if (sctp->sctp_conn_tfp != NULL && !caller_holds_lock) { 808*0Sstevel@tonic-gate /* in conn fanout; need to hold lock */ 809*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_conn_tfp->tf_lock); 810*0Sstevel@tonic-gate } 811*0Sstevel@tonic-gate 812*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp; fp = fpn) { 813*0Sstevel@tonic-gate fpn = fp->next; 814*0Sstevel@tonic-gate if (fp->ire != NULL) 815*0Sstevel@tonic-gate IRE_REFRELE_NOTR(fp->ire); 816*0Sstevel@tonic-gate kmem_cache_free(sctp_kmem_faddr_cache, fp); 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate sctp->sctp_faddrs = NULL; 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate if (sctp->sctp_conn_tfp != NULL && !caller_holds_lock) { 822*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_conn_tfp->tf_lock); 823*0Sstevel@tonic-gate } 824*0Sstevel@tonic-gate 825*0Sstevel@tonic-gate } 826*0Sstevel@tonic-gate 827*0Sstevel@tonic-gate void 828*0Sstevel@tonic-gate sctp_zap_addrs(sctp_t *sctp) 829*0Sstevel@tonic-gate { 830*0Sstevel@tonic-gate sctp_zap_faddrs(sctp, 0); 831*0Sstevel@tonic-gate sctp_free_saddrs(sctp); 832*0Sstevel@tonic-gate } 833*0Sstevel@tonic-gate 834*0Sstevel@tonic-gate /* 835*0Sstevel@tonic-gate * Initialize the IPv4 header. Loses any record of any IP options. 836*0Sstevel@tonic-gate */ 837*0Sstevel@tonic-gate int 838*0Sstevel@tonic-gate sctp_header_init_ipv4(sctp_t *sctp, int sleep) 839*0Sstevel@tonic-gate { 840*0Sstevel@tonic-gate sctp_hdr_t *sctph; 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * This is a simple initialization. If there's 844*0Sstevel@tonic-gate * already a template, it should never be too small, 845*0Sstevel@tonic-gate * so reuse it. Otherwise, allocate space for the new one. 846*0Sstevel@tonic-gate */ 847*0Sstevel@tonic-gate if (sctp->sctp_iphc != NULL) { 848*0Sstevel@tonic-gate ASSERT(sctp->sctp_iphc_len >= SCTP_MAX_COMBINED_HEADER_LENGTH); 849*0Sstevel@tonic-gate bzero(sctp->sctp_iphc, sctp->sctp_iphc_len); 850*0Sstevel@tonic-gate } else { 851*0Sstevel@tonic-gate sctp->sctp_iphc_len = SCTP_MAX_COMBINED_HEADER_LENGTH; 852*0Sstevel@tonic-gate sctp->sctp_iphc = kmem_zalloc(sctp->sctp_iphc_len, sleep); 853*0Sstevel@tonic-gate if (sctp->sctp_iphc == NULL) { 854*0Sstevel@tonic-gate sctp->sctp_iphc_len = 0; 855*0Sstevel@tonic-gate return (ENOMEM); 856*0Sstevel@tonic-gate } 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate sctp->sctp_ipha = (ipha_t *)sctp->sctp_iphc; 860*0Sstevel@tonic-gate 861*0Sstevel@tonic-gate sctp->sctp_hdr_len = sizeof (ipha_t) + sizeof (sctp_hdr_t); 862*0Sstevel@tonic-gate sctp->sctp_ip_hdr_len = sizeof (ipha_t); 863*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_length = htons(sizeof (ipha_t) + 864*0Sstevel@tonic-gate sizeof (sctp_hdr_t)); 865*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_version_and_hdr_length 866*0Sstevel@tonic-gate = (IP_VERSION << 4) | IP_SIMPLE_HDR_LENGTH_IN_WORDS; 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate /* 869*0Sstevel@tonic-gate * These two fields should be zero, and are already set above. 870*0Sstevel@tonic-gate * 871*0Sstevel@tonic-gate * sctp->sctp_ipha->ipha_ident, 872*0Sstevel@tonic-gate * sctp->sctp_ipha->ipha_fragment_offset_and_flags. 873*0Sstevel@tonic-gate */ 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_ttl = sctp_ipv4_ttl; 876*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_protocol = IPPROTO_SCTP; 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate sctph = (sctp_hdr_t *)(sctp->sctp_iphc + sizeof (ipha_t)); 879*0Sstevel@tonic-gate sctp->sctp_sctph = sctph; 880*0Sstevel@tonic-gate 881*0Sstevel@tonic-gate return (0); 882*0Sstevel@tonic-gate } 883*0Sstevel@tonic-gate 884*0Sstevel@tonic-gate /* 885*0Sstevel@tonic-gate * Update sctp_sticky_hdrs based on sctp_sticky_ipp. 886*0Sstevel@tonic-gate * The headers include ip6i_t (if needed), ip6_t, any sticky extension 887*0Sstevel@tonic-gate * headers, and the maximum size sctp header (to avoid reallocation 888*0Sstevel@tonic-gate * on the fly for additional sctp options). 889*0Sstevel@tonic-gate * Returns failure if can't allocate memory. 890*0Sstevel@tonic-gate */ 891*0Sstevel@tonic-gate int 892*0Sstevel@tonic-gate sctp_build_hdrs(sctp_t *sctp) 893*0Sstevel@tonic-gate { 894*0Sstevel@tonic-gate char *hdrs; 895*0Sstevel@tonic-gate uint_t hdrs_len; 896*0Sstevel@tonic-gate ip6i_t *ip6i; 897*0Sstevel@tonic-gate char buf[SCTP_MAX_HDR_LENGTH]; 898*0Sstevel@tonic-gate ip6_pkt_t *ipp = &sctp->sctp_sticky_ipp; 899*0Sstevel@tonic-gate in6_addr_t src; 900*0Sstevel@tonic-gate in6_addr_t dst; 901*0Sstevel@tonic-gate uint8_t hoplimit; 902*0Sstevel@tonic-gate /* 903*0Sstevel@tonic-gate * save the existing sctp header and source/dest IP addresses 904*0Sstevel@tonic-gate */ 905*0Sstevel@tonic-gate bcopy(sctp->sctp_sctph6, buf, sizeof (sctp_hdr_t)); 906*0Sstevel@tonic-gate src = sctp->sctp_ip6h->ip6_src; 907*0Sstevel@tonic-gate dst = sctp->sctp_ip6h->ip6_dst; 908*0Sstevel@tonic-gate hoplimit = sctp->sctp_ip6h->ip6_hops; 909*0Sstevel@tonic-gate hdrs_len = ip_total_hdrs_len_v6(ipp) + SCTP_MAX_HDR_LENGTH; 910*0Sstevel@tonic-gate ASSERT(hdrs_len != 0); 911*0Sstevel@tonic-gate if (hdrs_len > sctp->sctp_iphc6_len) { 912*0Sstevel@tonic-gate /* Need to reallocate */ 913*0Sstevel@tonic-gate hdrs = kmem_zalloc(hdrs_len, KM_NOSLEEP); 914*0Sstevel@tonic-gate if (hdrs == NULL) 915*0Sstevel@tonic-gate return (ENOMEM); 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate if (sctp->sctp_iphc6_len != 0) 918*0Sstevel@tonic-gate kmem_free(sctp->sctp_iphc6, sctp->sctp_iphc6_len); 919*0Sstevel@tonic-gate sctp->sctp_iphc6 = hdrs; 920*0Sstevel@tonic-gate sctp->sctp_iphc6_len = hdrs_len; 921*0Sstevel@tonic-gate } 922*0Sstevel@tonic-gate ip_build_hdrs_v6((uchar_t *)sctp->sctp_iphc6, 923*0Sstevel@tonic-gate hdrs_len - SCTP_MAX_HDR_LENGTH, ipp, IPPROTO_SCTP); 924*0Sstevel@tonic-gate 925*0Sstevel@tonic-gate /* Set header fields not in ipp */ 926*0Sstevel@tonic-gate if (ipp->ipp_fields & IPPF_HAS_IP6I) { 927*0Sstevel@tonic-gate ip6i = (ip6i_t *)sctp->sctp_iphc6; 928*0Sstevel@tonic-gate sctp->sctp_ip6h = (ip6_t *)&ip6i[1]; 929*0Sstevel@tonic-gate } else { 930*0Sstevel@tonic-gate sctp->sctp_ip6h = (ip6_t *)sctp->sctp_iphc6; 931*0Sstevel@tonic-gate } 932*0Sstevel@tonic-gate /* 933*0Sstevel@tonic-gate * sctp->sctp_ip_hdr_len will include ip6i_t if there is one. 934*0Sstevel@tonic-gate */ 935*0Sstevel@tonic-gate sctp->sctp_ip_hdr6_len = hdrs_len - SCTP_MAX_HDR_LENGTH; 936*0Sstevel@tonic-gate sctp->sctp_sctph6 = (sctp_hdr_t *)(sctp->sctp_iphc6 + 937*0Sstevel@tonic-gate sctp->sctp_ip_hdr6_len); 938*0Sstevel@tonic-gate sctp->sctp_hdr6_len = sctp->sctp_ip_hdr6_len + sizeof (sctp_hdr_t); 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate bcopy(buf, sctp->sctp_sctph6, sizeof (sctp_hdr_t)); 941*0Sstevel@tonic-gate 942*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_src = src; 943*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_dst = dst; 944*0Sstevel@tonic-gate /* 945*0Sstevel@tonic-gate * If IPV6_HOPLIMIT was set in ipp, use that value. 946*0Sstevel@tonic-gate * For sticky options, if it does not exist use 947*0Sstevel@tonic-gate * the default/saved value (which was set in ip_build_hdrs_v6()) 948*0Sstevel@tonic-gate * All this as per RFC 2922. 949*0Sstevel@tonic-gate */ 950*0Sstevel@tonic-gate if (!(ipp->ipp_fields & IPPF_HOPLIMIT)) 951*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_hops = hoplimit; 952*0Sstevel@tonic-gate /* 953*0Sstevel@tonic-gate * Set the IPv6 header payload length. 954*0Sstevel@tonic-gate * If there's an ip6i_t included, don't count it in the length. 955*0Sstevel@tonic-gate */ 956*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_plen = sctp->sctp_hdr6_len - IPV6_HDR_LEN; 957*0Sstevel@tonic-gate if (ipp->ipp_fields & IPPF_HAS_IP6I) 958*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_plen -= sizeof (ip6i_t); 959*0Sstevel@tonic-gate /* 960*0Sstevel@tonic-gate * If we're setting extension headers after a connection 961*0Sstevel@tonic-gate * has been established, and if we have a routing header 962*0Sstevel@tonic-gate * among the extension headers, call ip_massage_options_v6 to 963*0Sstevel@tonic-gate * manipulate the routing header/ip6_dst set the checksum 964*0Sstevel@tonic-gate * difference in the sctp header template. 965*0Sstevel@tonic-gate * (This happens in sctp_connect_ipv6 if the routing header 966*0Sstevel@tonic-gate * is set prior to the connect.) 967*0Sstevel@tonic-gate */ 968*0Sstevel@tonic-gate 969*0Sstevel@tonic-gate if ((sctp->sctp_state >= SCTPS_COOKIE_WAIT) && 970*0Sstevel@tonic-gate (sctp->sctp_sticky_ipp.ipp_fields & IPPF_RTHDR)) { 971*0Sstevel@tonic-gate ip6_rthdr_t *rth; 972*0Sstevel@tonic-gate 973*0Sstevel@tonic-gate rth = ip_find_rthdr_v6(sctp->sctp_ip6h, 974*0Sstevel@tonic-gate (uint8_t *)sctp->sctp_sctph6); 975*0Sstevel@tonic-gate if (rth != NULL) 976*0Sstevel@tonic-gate (void) ip_massage_options_v6(sctp->sctp_ip6h, rth); 977*0Sstevel@tonic-gate } 978*0Sstevel@tonic-gate return (0); 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate /* 982*0Sstevel@tonic-gate * Initialize the IPv6 header. Loses any record of any IPv6 extension headers. 983*0Sstevel@tonic-gate */ 984*0Sstevel@tonic-gate int 985*0Sstevel@tonic-gate sctp_header_init_ipv6(sctp_t *sctp, int sleep) 986*0Sstevel@tonic-gate { 987*0Sstevel@tonic-gate sctp_hdr_t *sctph; 988*0Sstevel@tonic-gate 989*0Sstevel@tonic-gate /* 990*0Sstevel@tonic-gate * This is a simple initialization. If there's 991*0Sstevel@tonic-gate * already a template, it should never be too small, 992*0Sstevel@tonic-gate * so reuse it. Otherwise, allocate space for the new one. 993*0Sstevel@tonic-gate * Ensure that there is enough space to "downgrade" the sctp_t 994*0Sstevel@tonic-gate * to an IPv4 sctp_t. This requires having space for a full load 995*0Sstevel@tonic-gate * of IPv4 options 996*0Sstevel@tonic-gate */ 997*0Sstevel@tonic-gate if (sctp->sctp_iphc6 != NULL) { 998*0Sstevel@tonic-gate ASSERT(sctp->sctp_iphc6_len >= 999*0Sstevel@tonic-gate SCTP_MAX_COMBINED_HEADER_LENGTH); 1000*0Sstevel@tonic-gate bzero(sctp->sctp_iphc6, sctp->sctp_iphc6_len); 1001*0Sstevel@tonic-gate } else { 1002*0Sstevel@tonic-gate sctp->sctp_iphc6_len = SCTP_MAX_COMBINED_HEADER_LENGTH; 1003*0Sstevel@tonic-gate sctp->sctp_iphc6 = kmem_zalloc(sctp->sctp_iphc_len, sleep); 1004*0Sstevel@tonic-gate if (sctp->sctp_iphc6 == NULL) { 1005*0Sstevel@tonic-gate sctp->sctp_iphc6_len = 0; 1006*0Sstevel@tonic-gate return (ENOMEM); 1007*0Sstevel@tonic-gate } 1008*0Sstevel@tonic-gate } 1009*0Sstevel@tonic-gate sctp->sctp_hdr6_len = IPV6_HDR_LEN + sizeof (sctp_hdr_t); 1010*0Sstevel@tonic-gate sctp->sctp_ip_hdr6_len = IPV6_HDR_LEN; 1011*0Sstevel@tonic-gate sctp->sctp_ip6h = (ip6_t *)sctp->sctp_iphc6; 1012*0Sstevel@tonic-gate 1013*0Sstevel@tonic-gate /* Initialize the header template */ 1014*0Sstevel@tonic-gate 1015*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 1016*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_plen = ntohs(sizeof (sctp_hdr_t)); 1017*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_nxt = IPPROTO_SCTP; 1018*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_hops = sctp_ipv6_hoplimit; 1019*0Sstevel@tonic-gate 1020*0Sstevel@tonic-gate sctph = (sctp_hdr_t *)(sctp->sctp_iphc6 + IPV6_HDR_LEN); 1021*0Sstevel@tonic-gate sctp->sctp_sctph6 = sctph; 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate return (0); 1024*0Sstevel@tonic-gate } 1025*0Sstevel@tonic-gate 1026*0Sstevel@tonic-gate /* 1027*0Sstevel@tonic-gate * XXX implement more sophisticated logic 1028*0Sstevel@tonic-gate */ 1029*0Sstevel@tonic-gate void 1030*0Sstevel@tonic-gate sctp_set_hdraddrs(sctp_t *sctp) 1031*0Sstevel@tonic-gate { 1032*0Sstevel@tonic-gate sctp_faddr_t *fp; 1033*0Sstevel@tonic-gate int gotv4 = 0; 1034*0Sstevel@tonic-gate int gotv6 = 0; 1035*0Sstevel@tonic-gate 1036*0Sstevel@tonic-gate ASSERT(sctp->sctp_faddrs != NULL); 1037*0Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 1038*0Sstevel@tonic-gate 1039*0Sstevel@tonic-gate /* Set up using the primary first */ 1040*0Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(&sctp->sctp_primary->faddr)) { 1041*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&sctp->sctp_primary->faddr, 1042*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_dst); 1043*0Sstevel@tonic-gate /* saddr may be unspec; make_mp() will handle this */ 1044*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&sctp->sctp_primary->saddr, 1045*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_src); 1046*0Sstevel@tonic-gate gotv4 = 1; 1047*0Sstevel@tonic-gate if (sctp->sctp_ipversion == IPV4_VERSION) { 1048*0Sstevel@tonic-gate goto copyports; 1049*0Sstevel@tonic-gate } 1050*0Sstevel@tonic-gate } else { 1051*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_dst = sctp->sctp_primary->faddr; 1052*0Sstevel@tonic-gate /* saddr may be unspec; make_mp() will handle this */ 1053*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_src = sctp->sctp_primary->saddr; 1054*0Sstevel@tonic-gate gotv6 = 1; 1055*0Sstevel@tonic-gate } 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 1058*0Sstevel@tonic-gate if (!gotv4 && IN6_IS_ADDR_V4MAPPED(&fp->faddr)) { 1059*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->faddr, 1060*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_dst); 1061*0Sstevel@tonic-gate /* copy in the faddr_t's saddr */ 1062*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->saddr, 1063*0Sstevel@tonic-gate sctp->sctp_ipha->ipha_src); 1064*0Sstevel@tonic-gate gotv4 = 1; 1065*0Sstevel@tonic-gate if (sctp->sctp_ipversion == IPV4_VERSION || gotv6) { 1066*0Sstevel@tonic-gate break; 1067*0Sstevel@tonic-gate } 1068*0Sstevel@tonic-gate } else if (!gotv6) { 1069*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_dst = fp->faddr; 1070*0Sstevel@tonic-gate /* copy in the faddr_t's saddr */ 1071*0Sstevel@tonic-gate sctp->sctp_ip6h->ip6_src = fp->saddr; 1072*0Sstevel@tonic-gate gotv6 = 1; 1073*0Sstevel@tonic-gate if (gotv4) { 1074*0Sstevel@tonic-gate break; 1075*0Sstevel@tonic-gate } 1076*0Sstevel@tonic-gate } 1077*0Sstevel@tonic-gate } 1078*0Sstevel@tonic-gate 1079*0Sstevel@tonic-gate copyports: 1080*0Sstevel@tonic-gate /* copy in the ports for good measure */ 1081*0Sstevel@tonic-gate sctp->sctp_sctph->sh_sport = sctp->sctp_lport; 1082*0Sstevel@tonic-gate sctp->sctp_sctph->sh_dport = sctp->sctp_fport; 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate sctp->sctp_sctph6->sh_sport = sctp->sctp_lport; 1085*0Sstevel@tonic-gate sctp->sctp_sctph6->sh_dport = sctp->sctp_fport; 1086*0Sstevel@tonic-gate } 1087*0Sstevel@tonic-gate 1088*0Sstevel@tonic-gate void 1089*0Sstevel@tonic-gate sctp_add_unrec_parm(sctp_parm_hdr_t *uph, mblk_t **errmp) 1090*0Sstevel@tonic-gate { 1091*0Sstevel@tonic-gate mblk_t *mp; 1092*0Sstevel@tonic-gate sctp_parm_hdr_t *ph; 1093*0Sstevel@tonic-gate size_t len; 1094*0Sstevel@tonic-gate int pad; 1095*0Sstevel@tonic-gate 1096*0Sstevel@tonic-gate len = sizeof (*ph) + ntohs(uph->sph_len); 1097*0Sstevel@tonic-gate if ((pad = len % 4) != 0) { 1098*0Sstevel@tonic-gate pad = 4 - pad; 1099*0Sstevel@tonic-gate len += pad; 1100*0Sstevel@tonic-gate } 1101*0Sstevel@tonic-gate mp = allocb(len, BPRI_MED); 1102*0Sstevel@tonic-gate if (mp == NULL) { 1103*0Sstevel@tonic-gate return; 1104*0Sstevel@tonic-gate } 1105*0Sstevel@tonic-gate 1106*0Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)(mp->b_rptr); 1107*0Sstevel@tonic-gate ph->sph_type = htons(PARM_UNRECOGNIZED); 1108*0Sstevel@tonic-gate ph->sph_len = htons(len - pad); 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate /* copy in the unrecognized parameter */ 1111*0Sstevel@tonic-gate bcopy(uph, ph + 1, ntohs(uph->sph_len)); 1112*0Sstevel@tonic-gate 1113*0Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + len; 1114*0Sstevel@tonic-gate if (*errmp != NULL) { 1115*0Sstevel@tonic-gate linkb(*errmp, mp); 1116*0Sstevel@tonic-gate } else { 1117*0Sstevel@tonic-gate *errmp = mp; 1118*0Sstevel@tonic-gate } 1119*0Sstevel@tonic-gate } 1120*0Sstevel@tonic-gate 1121*0Sstevel@tonic-gate /* 1122*0Sstevel@tonic-gate * o Bounds checking 1123*0Sstevel@tonic-gate * o Updates remaining 1124*0Sstevel@tonic-gate * o Checks alignment 1125*0Sstevel@tonic-gate */ 1126*0Sstevel@tonic-gate sctp_parm_hdr_t * 1127*0Sstevel@tonic-gate sctp_next_parm(sctp_parm_hdr_t *current, ssize_t *remaining) 1128*0Sstevel@tonic-gate { 1129*0Sstevel@tonic-gate int pad; 1130*0Sstevel@tonic-gate uint16_t len; 1131*0Sstevel@tonic-gate 1132*0Sstevel@tonic-gate len = ntohs(current->sph_len); 1133*0Sstevel@tonic-gate *remaining -= len; 1134*0Sstevel@tonic-gate if (*remaining < sizeof (*current) || len < sizeof (*current)) { 1135*0Sstevel@tonic-gate return (NULL); 1136*0Sstevel@tonic-gate } 1137*0Sstevel@tonic-gate if ((pad = len & (SCTP_ALIGN - 1)) != 0) { 1138*0Sstevel@tonic-gate pad = SCTP_ALIGN - pad; 1139*0Sstevel@tonic-gate *remaining -= pad; 1140*0Sstevel@tonic-gate } 1141*0Sstevel@tonic-gate /*LINTED pointer cast may result in improper alignment*/ 1142*0Sstevel@tonic-gate current = (sctp_parm_hdr_t *)((char *)current + len + pad); 1143*0Sstevel@tonic-gate return (current); 1144*0Sstevel@tonic-gate } 1145*0Sstevel@tonic-gate 1146*0Sstevel@tonic-gate /* 1147*0Sstevel@tonic-gate * Sets the address parameters given in the INIT chunk into sctp's 1148*0Sstevel@tonic-gate * faddrs; if psctp is non-NULL, copies psctp's saddrs. If there are 1149*0Sstevel@tonic-gate * no address parameters in the INIT chunk, a single faddr is created 1150*0Sstevel@tonic-gate * from the ip hdr at the beginning of pkt. 1151*0Sstevel@tonic-gate * If there already are existing addresses hanging from sctp, merge 1152*0Sstevel@tonic-gate * them in, if the old info contains addresses which are not present 1153*0Sstevel@tonic-gate * in this new info, get rid of them, and clean the pointers if there's 1154*0Sstevel@tonic-gate * messages which have this as their target address. 1155*0Sstevel@tonic-gate * 1156*0Sstevel@tonic-gate * Returns 0 on success, sys errno on failure 1157*0Sstevel@tonic-gate */ 1158*0Sstevel@tonic-gate int 1159*0Sstevel@tonic-gate sctp_get_addrparams(sctp_t *sctp, sctp_t *psctp, mblk_t *pkt, 1160*0Sstevel@tonic-gate sctp_chunk_hdr_t *ich, uint_t *sctp_options) 1161*0Sstevel@tonic-gate { 1162*0Sstevel@tonic-gate sctp_init_chunk_t *init; 1163*0Sstevel@tonic-gate ipha_t *iph; 1164*0Sstevel@tonic-gate ip6_t *ip6h; 1165*0Sstevel@tonic-gate in6_addr_t hdraddr[1]; 1166*0Sstevel@tonic-gate sctp_parm_hdr_t *ph; 1167*0Sstevel@tonic-gate ssize_t remaining; 1168*0Sstevel@tonic-gate int isv4; 1169*0Sstevel@tonic-gate int err; 1170*0Sstevel@tonic-gate sctp_faddr_t *fp; 1171*0Sstevel@tonic-gate 1172*0Sstevel@tonic-gate if (sctp_options != NULL) 1173*0Sstevel@tonic-gate *sctp_options = 0; 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate /* inherit laddrs, if given */ 1176*0Sstevel@tonic-gate if (psctp != NULL && psctp->sctp_nsaddrs > 0) { 1177*0Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs == 0); 1178*0Sstevel@tonic-gate 1179*0Sstevel@tonic-gate err = sctp_dup_saddrs(psctp, sctp, KM_NOSLEEP); 1180*0Sstevel@tonic-gate if (err != 0) 1181*0Sstevel@tonic-gate return (err); 1182*0Sstevel@tonic-gate } 1183*0Sstevel@tonic-gate 1184*0Sstevel@tonic-gate /* extract the address from the IP header */ 1185*0Sstevel@tonic-gate isv4 = (IPH_HDR_VERSION(pkt->b_rptr) == IPV4_VERSION); 1186*0Sstevel@tonic-gate if (isv4) { 1187*0Sstevel@tonic-gate iph = (ipha_t *)pkt->b_rptr; 1188*0Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(iph->ipha_src, hdraddr); 1189*0Sstevel@tonic-gate } else { 1190*0Sstevel@tonic-gate ip6h = (ip6_t *)pkt->b_rptr; 1191*0Sstevel@tonic-gate hdraddr[0] = ip6h->ip6_src; 1192*0Sstevel@tonic-gate } 1193*0Sstevel@tonic-gate 1194*0Sstevel@tonic-gate /* For loopback connections ignore address list */ 1195*0Sstevel@tonic-gate if (sctp->sctp_loopback) 1196*0Sstevel@tonic-gate goto get_from_iphdr; 1197*0Sstevel@tonic-gate 1198*0Sstevel@tonic-gate /* Walk the params in the INIT [ACK], pulling out addr params */ 1199*0Sstevel@tonic-gate remaining = ntohs(ich->sch_len) - sizeof (*ich) - 1200*0Sstevel@tonic-gate sizeof (sctp_init_chunk_t); 1201*0Sstevel@tonic-gate if (remaining < sizeof (*ph)) { 1202*0Sstevel@tonic-gate /* no parameters */ 1203*0Sstevel@tonic-gate goto get_from_iphdr; 1204*0Sstevel@tonic-gate } 1205*0Sstevel@tonic-gate init = (sctp_init_chunk_t *)(ich + 1); 1206*0Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)(init + 1); 1207*0Sstevel@tonic-gate 1208*0Sstevel@tonic-gate while (ph != NULL) { 1209*0Sstevel@tonic-gate /* params will have already been byteordered when validating */ 1210*0Sstevel@tonic-gate if (ph->sph_type == htons(PARM_ADDR4)) { 1211*0Sstevel@tonic-gate if (remaining >= PARM_ADDR4_LEN) { 1212*0Sstevel@tonic-gate in6_addr_t addr; 1213*0Sstevel@tonic-gate ipaddr_t ta; 1214*0Sstevel@tonic-gate 1215*0Sstevel@tonic-gate /* 1216*0Sstevel@tonic-gate * Screen out broad/multicasts & loopback. 1217*0Sstevel@tonic-gate * If the endpoint only accepts v6 address, 1218*0Sstevel@tonic-gate * go to the next one. 1219*0Sstevel@tonic-gate */ 1220*0Sstevel@tonic-gate bcopy(ph + 1, &ta, sizeof (ta)); 1221*0Sstevel@tonic-gate if (ta == 0 || 1222*0Sstevel@tonic-gate ta == INADDR_BROADCAST || 1223*0Sstevel@tonic-gate ta == htonl(INADDR_LOOPBACK) || 1224*0Sstevel@tonic-gate IN_MULTICAST(ta) || 1225*0Sstevel@tonic-gate sctp->sctp_connp->conn_ipv6_v6only) { 1226*0Sstevel@tonic-gate goto next; 1227*0Sstevel@tonic-gate } 1228*0Sstevel@tonic-gate /* 1229*0Sstevel@tonic-gate * XXX also need to check for subnet 1230*0Sstevel@tonic-gate * broadcasts. This should probably 1231*0Sstevel@tonic-gate * wait until we have full access 1232*0Sstevel@tonic-gate * to the ILL tables. 1233*0Sstevel@tonic-gate */ 1234*0Sstevel@tonic-gate 1235*0Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED((struct in_addr *) 1236*0Sstevel@tonic-gate (ph + 1), &addr); 1237*0Sstevel@tonic-gate /* Check for duplicate. */ 1238*0Sstevel@tonic-gate if (sctp_lookup_faddr(sctp, &addr) != NULL) 1239*0Sstevel@tonic-gate goto next; 1240*0Sstevel@tonic-gate 1241*0Sstevel@tonic-gate /* OK, add it to the faddr set */ 1242*0Sstevel@tonic-gate if (sctp_add_faddr(sctp, &addr, 1243*0Sstevel@tonic-gate KM_NOSLEEP) != 0) { 1244*0Sstevel@tonic-gate return (ENOMEM); 1245*0Sstevel@tonic-gate } 1246*0Sstevel@tonic-gate } 1247*0Sstevel@tonic-gate } else if (ph->sph_type == htons(PARM_ADDR6) && 1248*0Sstevel@tonic-gate sctp->sctp_family == AF_INET6) { 1249*0Sstevel@tonic-gate /* An v4 socket should not take v6 addresses. */ 1250*0Sstevel@tonic-gate if (remaining >= PARM_ADDR6_LEN) { 1251*0Sstevel@tonic-gate in6_addr_t *addr6; 1252*0Sstevel@tonic-gate 1253*0Sstevel@tonic-gate addr6 = (in6_addr_t *)(ph + 1); 1254*0Sstevel@tonic-gate /* 1255*0Sstevel@tonic-gate * Screen out link locals, mcast, loopback 1256*0Sstevel@tonic-gate * and bogus v6 address. 1257*0Sstevel@tonic-gate */ 1258*0Sstevel@tonic-gate if (IN6_IS_ADDR_LINKLOCAL(addr6) || 1259*0Sstevel@tonic-gate IN6_IS_ADDR_MULTICAST(addr6) || 1260*0Sstevel@tonic-gate IN6_IS_ADDR_LOOPBACK(addr6) || 1261*0Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(addr6)) { 1262*0Sstevel@tonic-gate goto next; 1263*0Sstevel@tonic-gate } 1264*0Sstevel@tonic-gate /* Check for duplicate. */ 1265*0Sstevel@tonic-gate if (sctp_lookup_faddr(sctp, addr6) != NULL) 1266*0Sstevel@tonic-gate goto next; 1267*0Sstevel@tonic-gate 1268*0Sstevel@tonic-gate if (sctp_add_faddr(sctp, 1269*0Sstevel@tonic-gate (in6_addr_t *)(ph + 1), KM_NOSLEEP) != 0) { 1270*0Sstevel@tonic-gate return (ENOMEM); 1271*0Sstevel@tonic-gate } 1272*0Sstevel@tonic-gate } 1273*0Sstevel@tonic-gate } else if (ph->sph_type == htons(PARM_FORWARD_TSN)) { 1274*0Sstevel@tonic-gate if (sctp_options != NULL) 1275*0Sstevel@tonic-gate *sctp_options |= SCTP_PRSCTP_OPTION; 1276*0Sstevel@tonic-gate } /* else; skip */ 1277*0Sstevel@tonic-gate 1278*0Sstevel@tonic-gate next: 1279*0Sstevel@tonic-gate ph = sctp_next_parm(ph, &remaining); 1280*0Sstevel@tonic-gate } 1281*0Sstevel@tonic-gate 1282*0Sstevel@tonic-gate get_from_iphdr: 1283*0Sstevel@tonic-gate /* Make sure the header's addr is in the list */ 1284*0Sstevel@tonic-gate fp = sctp_lookup_faddr(sctp, hdraddr); 1285*0Sstevel@tonic-gate if (fp == NULL) { 1286*0Sstevel@tonic-gate /* not included; add it now */ 1287*0Sstevel@tonic-gate if (sctp_add_faddr_first(sctp, hdraddr, KM_NOSLEEP) == -1) 1288*0Sstevel@tonic-gate return (ENOMEM); 1289*0Sstevel@tonic-gate 1290*0Sstevel@tonic-gate /* sctp_faddrs will be the hdr addr */ 1291*0Sstevel@tonic-gate fp = sctp->sctp_faddrs; 1292*0Sstevel@tonic-gate } 1293*0Sstevel@tonic-gate /* make the header addr the primary */ 1294*0Sstevel@tonic-gate sctp->sctp_primary = fp; 1295*0Sstevel@tonic-gate sctp->sctp_current = fp; 1296*0Sstevel@tonic-gate sctp->sctp_mss = fp->sfa_pmss; 1297*0Sstevel@tonic-gate 1298*0Sstevel@tonic-gate return (0); 1299*0Sstevel@tonic-gate } 1300*0Sstevel@tonic-gate 1301*0Sstevel@tonic-gate /* 1302*0Sstevel@tonic-gate * Returns 0 if the check failed and the restart should be refused, 1303*0Sstevel@tonic-gate * 1 if the check succeeded. 1304*0Sstevel@tonic-gate */ 1305*0Sstevel@tonic-gate int 1306*0Sstevel@tonic-gate sctp_secure_restart_check(mblk_t *pkt, sctp_chunk_hdr_t *ich, uint32_t ports, 1307*0Sstevel@tonic-gate int sleep) 1308*0Sstevel@tonic-gate { 1309*0Sstevel@tonic-gate sctp_faddr_t *fp, *fpa, *fphead = NULL; 1310*0Sstevel@tonic-gate sctp_parm_hdr_t *ph; 1311*0Sstevel@tonic-gate ssize_t remaining; 1312*0Sstevel@tonic-gate int isv4; 1313*0Sstevel@tonic-gate ipha_t *iph; 1314*0Sstevel@tonic-gate ip6_t *ip6h; 1315*0Sstevel@tonic-gate in6_addr_t hdraddr[1]; 1316*0Sstevel@tonic-gate int retval = 0; 1317*0Sstevel@tonic-gate sctp_tf_t *tf; 1318*0Sstevel@tonic-gate sctp_t *sctp; 1319*0Sstevel@tonic-gate int compres; 1320*0Sstevel@tonic-gate sctp_init_chunk_t *init; 1321*0Sstevel@tonic-gate int nadded = 0; 1322*0Sstevel@tonic-gate 1323*0Sstevel@tonic-gate /* extract the address from the IP header */ 1324*0Sstevel@tonic-gate isv4 = (IPH_HDR_VERSION(pkt->b_rptr) == IPV4_VERSION); 1325*0Sstevel@tonic-gate if (isv4) { 1326*0Sstevel@tonic-gate iph = (ipha_t *)pkt->b_rptr; 1327*0Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(iph->ipha_src, hdraddr); 1328*0Sstevel@tonic-gate } else { 1329*0Sstevel@tonic-gate ip6h = (ip6_t *)pkt->b_rptr; 1330*0Sstevel@tonic-gate hdraddr[0] = ip6h->ip6_src; 1331*0Sstevel@tonic-gate } 1332*0Sstevel@tonic-gate 1333*0Sstevel@tonic-gate /* Walk the params in the INIT [ACK], pulling out addr params */ 1334*0Sstevel@tonic-gate remaining = ntohs(ich->sch_len) - sizeof (*ich) - 1335*0Sstevel@tonic-gate sizeof (sctp_init_chunk_t); 1336*0Sstevel@tonic-gate if (remaining < sizeof (*ph)) { 1337*0Sstevel@tonic-gate /* no parameters; restart OK */ 1338*0Sstevel@tonic-gate return (1); 1339*0Sstevel@tonic-gate } 1340*0Sstevel@tonic-gate init = (sctp_init_chunk_t *)(ich + 1); 1341*0Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)(init + 1); 1342*0Sstevel@tonic-gate 1343*0Sstevel@tonic-gate while (ph != NULL) { 1344*0Sstevel@tonic-gate /* params will have already been byteordered when validating */ 1345*0Sstevel@tonic-gate if (ph->sph_type == htons(PARM_ADDR4)) { 1346*0Sstevel@tonic-gate if (remaining >= PARM_ADDR4_LEN) { 1347*0Sstevel@tonic-gate in6_addr_t addr; 1348*0Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED((struct in_addr *) 1349*0Sstevel@tonic-gate (ph + 1), &addr); 1350*0Sstevel@tonic-gate fpa = kmem_cache_alloc(sctp_kmem_faddr_cache, 1351*0Sstevel@tonic-gate sleep); 1352*0Sstevel@tonic-gate if (!fpa) { 1353*0Sstevel@tonic-gate goto done; 1354*0Sstevel@tonic-gate } 1355*0Sstevel@tonic-gate bzero(fpa, sizeof (*fpa)); 1356*0Sstevel@tonic-gate fpa->faddr = addr; 1357*0Sstevel@tonic-gate fpa->next = NULL; 1358*0Sstevel@tonic-gate } 1359*0Sstevel@tonic-gate } else if (ph->sph_type == htons(PARM_ADDR6)) { 1360*0Sstevel@tonic-gate if (remaining >= PARM_ADDR6_LEN) { 1361*0Sstevel@tonic-gate fpa = kmem_cache_alloc(sctp_kmem_faddr_cache, 1362*0Sstevel@tonic-gate sleep); 1363*0Sstevel@tonic-gate if (!fpa) { 1364*0Sstevel@tonic-gate goto done; 1365*0Sstevel@tonic-gate } 1366*0Sstevel@tonic-gate bzero(fpa, sizeof (*fpa)); 1367*0Sstevel@tonic-gate bcopy(ph + 1, &fpa->faddr, 1368*0Sstevel@tonic-gate sizeof (fpa->faddr)); 1369*0Sstevel@tonic-gate fpa->next = NULL; 1370*0Sstevel@tonic-gate } 1371*0Sstevel@tonic-gate } else { 1372*0Sstevel@tonic-gate /* else not addr param; skip */ 1373*0Sstevel@tonic-gate fpa = NULL; 1374*0Sstevel@tonic-gate } 1375*0Sstevel@tonic-gate /* link in the new addr, if it was an addr param */ 1376*0Sstevel@tonic-gate if (fpa) { 1377*0Sstevel@tonic-gate if (!fphead) { 1378*0Sstevel@tonic-gate fphead = fpa; 1379*0Sstevel@tonic-gate fp = fphead; 1380*0Sstevel@tonic-gate } else { 1381*0Sstevel@tonic-gate fp->next = fpa; 1382*0Sstevel@tonic-gate fp = fpa; 1383*0Sstevel@tonic-gate } 1384*0Sstevel@tonic-gate } 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate ph = sctp_next_parm(ph, &remaining); 1387*0Sstevel@tonic-gate } 1388*0Sstevel@tonic-gate 1389*0Sstevel@tonic-gate if (fphead == NULL) { 1390*0Sstevel@tonic-gate /* no addr parameters; restart OK */ 1391*0Sstevel@tonic-gate return (1); 1392*0Sstevel@tonic-gate } 1393*0Sstevel@tonic-gate 1394*0Sstevel@tonic-gate /* 1395*0Sstevel@tonic-gate * got at least one; make sure the header's addr is 1396*0Sstevel@tonic-gate * in the list 1397*0Sstevel@tonic-gate */ 1398*0Sstevel@tonic-gate fp = sctp_lookup_faddr_nosctp(fphead, hdraddr); 1399*0Sstevel@tonic-gate if (!fp) { 1400*0Sstevel@tonic-gate /* not included; add it now */ 1401*0Sstevel@tonic-gate fp = kmem_cache_alloc(sctp_kmem_faddr_cache, sleep); 1402*0Sstevel@tonic-gate if (!fp) { 1403*0Sstevel@tonic-gate goto done; 1404*0Sstevel@tonic-gate } 1405*0Sstevel@tonic-gate bzero(fp, sizeof (*fp)); 1406*0Sstevel@tonic-gate fp->faddr = *hdraddr; 1407*0Sstevel@tonic-gate fp->next = fphead; 1408*0Sstevel@tonic-gate fphead = fp; 1409*0Sstevel@tonic-gate } 1410*0Sstevel@tonic-gate 1411*0Sstevel@tonic-gate /* 1412*0Sstevel@tonic-gate * Now, we can finally do the check: For each sctp instance 1413*0Sstevel@tonic-gate * on the hash line for ports, compare its faddr set against 1414*0Sstevel@tonic-gate * the new one. If the new one is a strict subset of any 1415*0Sstevel@tonic-gate * existing sctp's faddrs, the restart is OK. However, if there 1416*0Sstevel@tonic-gate * is an overlap, this could be an attack, so return failure. 1417*0Sstevel@tonic-gate * If all sctp's faddrs are disjoint, this is a legitimate new 1418*0Sstevel@tonic-gate * association. 1419*0Sstevel@tonic-gate */ 1420*0Sstevel@tonic-gate tf = &(sctp_conn_fanout[SCTP_CONN_HASH(ports)]); 1421*0Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 1422*0Sstevel@tonic-gate 1423*0Sstevel@tonic-gate for (sctp = tf->tf_sctp; sctp; sctp = sctp->sctp_conn_hash_next) { 1424*0Sstevel@tonic-gate if (ports != sctp->sctp_ports) { 1425*0Sstevel@tonic-gate continue; 1426*0Sstevel@tonic-gate } 1427*0Sstevel@tonic-gate compres = sctp_compare_faddrsets(fphead, sctp->sctp_faddrs); 1428*0Sstevel@tonic-gate if (compres <= SCTP_ADDR_SUBSET) { 1429*0Sstevel@tonic-gate retval = 1; 1430*0Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 1431*0Sstevel@tonic-gate goto done; 1432*0Sstevel@tonic-gate } 1433*0Sstevel@tonic-gate if (compres == SCTP_ADDR_OVERLAP) { 1434*0Sstevel@tonic-gate dprint(1, 1435*0Sstevel@tonic-gate ("new assoc from %x:%x:%x:%x overlaps with %p\n", 1436*0Sstevel@tonic-gate SCTP_PRINTADDR(*hdraddr), sctp)); 1437*0Sstevel@tonic-gate /* 1438*0Sstevel@tonic-gate * While we still hold the lock, we need to 1439*0Sstevel@tonic-gate * figure out which addresses have been 1440*0Sstevel@tonic-gate * added so we can include them in the abort 1441*0Sstevel@tonic-gate * we will send back. Since these faddrs will 1442*0Sstevel@tonic-gate * never be used, we overload the rto field 1443*0Sstevel@tonic-gate * here, setting it to 0 if the address was 1444*0Sstevel@tonic-gate * not added, 1 if it was added. 1445*0Sstevel@tonic-gate */ 1446*0Sstevel@tonic-gate for (fp = fphead; fp; fp = fp->next) { 1447*0Sstevel@tonic-gate if (sctp_lookup_faddr(sctp, &fp->faddr)) { 1448*0Sstevel@tonic-gate fp->rto = 0; 1449*0Sstevel@tonic-gate } else { 1450*0Sstevel@tonic-gate fp->rto = 1; 1451*0Sstevel@tonic-gate nadded++; 1452*0Sstevel@tonic-gate } 1453*0Sstevel@tonic-gate } 1454*0Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 1455*0Sstevel@tonic-gate goto done; 1456*0Sstevel@tonic-gate } 1457*0Sstevel@tonic-gate } 1458*0Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 1459*0Sstevel@tonic-gate 1460*0Sstevel@tonic-gate /* All faddrs are disjoint; legit new association */ 1461*0Sstevel@tonic-gate retval = 1; 1462*0Sstevel@tonic-gate 1463*0Sstevel@tonic-gate done: 1464*0Sstevel@tonic-gate /* If are attempted adds, send back an abort listing the addrs */ 1465*0Sstevel@tonic-gate if (nadded > 0) { 1466*0Sstevel@tonic-gate void *dtail; 1467*0Sstevel@tonic-gate size_t dlen; 1468*0Sstevel@tonic-gate 1469*0Sstevel@tonic-gate dtail = kmem_alloc(PARM_ADDR6_LEN * nadded, KM_NOSLEEP); 1470*0Sstevel@tonic-gate if (dtail == NULL) { 1471*0Sstevel@tonic-gate goto cleanup; 1472*0Sstevel@tonic-gate } 1473*0Sstevel@tonic-gate 1474*0Sstevel@tonic-gate ph = dtail; 1475*0Sstevel@tonic-gate dlen = 0; 1476*0Sstevel@tonic-gate for (fp = fphead; fp; fp = fp->next) { 1477*0Sstevel@tonic-gate if (fp->rto == 0) { 1478*0Sstevel@tonic-gate continue; 1479*0Sstevel@tonic-gate } 1480*0Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(&fp->faddr)) { 1481*0Sstevel@tonic-gate ipaddr_t addr4; 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate ph->sph_type = htons(PARM_ADDR4); 1484*0Sstevel@tonic-gate ph->sph_len = htons(PARM_ADDR4_LEN); 1485*0Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&fp->faddr, addr4); 1486*0Sstevel@tonic-gate ph++; 1487*0Sstevel@tonic-gate bcopy(&addr4, ph, sizeof (addr4)); 1488*0Sstevel@tonic-gate ph = (sctp_parm_hdr_t *) 1489*0Sstevel@tonic-gate ((char *)ph + sizeof (addr4)); 1490*0Sstevel@tonic-gate dlen += PARM_ADDR4_LEN; 1491*0Sstevel@tonic-gate } else { 1492*0Sstevel@tonic-gate ph->sph_type = htons(PARM_ADDR6); 1493*0Sstevel@tonic-gate ph->sph_len = htons(PARM_ADDR6_LEN); 1494*0Sstevel@tonic-gate ph++; 1495*0Sstevel@tonic-gate bcopy(&fp->faddr, ph, sizeof (fp->faddr)); 1496*0Sstevel@tonic-gate ph = (sctp_parm_hdr_t *) 1497*0Sstevel@tonic-gate ((char *)ph + sizeof (fp->faddr)); 1498*0Sstevel@tonic-gate dlen += PARM_ADDR6_LEN; 1499*0Sstevel@tonic-gate } 1500*0Sstevel@tonic-gate } 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate /* Send off the abort */ 1503*0Sstevel@tonic-gate sctp_send_abort(sctp, sctp_init2vtag(ich), 1504*0Sstevel@tonic-gate SCTP_ERR_RESTART_NEW_ADDRS, dtail, dlen, pkt, 0, B_TRUE); 1505*0Sstevel@tonic-gate 1506*0Sstevel@tonic-gate kmem_free(dtail, PARM_ADDR6_LEN * nadded); 1507*0Sstevel@tonic-gate } 1508*0Sstevel@tonic-gate 1509*0Sstevel@tonic-gate cleanup: 1510*0Sstevel@tonic-gate /* Clean up */ 1511*0Sstevel@tonic-gate if (fphead) { 1512*0Sstevel@tonic-gate sctp_faddr_t *fpn; 1513*0Sstevel@tonic-gate for (fp = fphead; fp; fp = fpn) { 1514*0Sstevel@tonic-gate fpn = fp->next; 1515*0Sstevel@tonic-gate kmem_cache_free(sctp_kmem_faddr_cache, fp); 1516*0Sstevel@tonic-gate } 1517*0Sstevel@tonic-gate } 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate return (retval); 1520*0Sstevel@tonic-gate } 1521*0Sstevel@tonic-gate 1522*0Sstevel@tonic-gate void 1523*0Sstevel@tonic-gate sctp_congest_reset(sctp_t *sctp) 1524*0Sstevel@tonic-gate { 1525*0Sstevel@tonic-gate sctp_faddr_t *fp; 1526*0Sstevel@tonic-gate 1527*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 1528*0Sstevel@tonic-gate fp->ssthresh = sctp_initial_mtu; 1529*0Sstevel@tonic-gate fp->cwnd = fp->sfa_pmss * sctp_slow_start_initial; 1530*0Sstevel@tonic-gate fp->suna = 0; 1531*0Sstevel@tonic-gate fp->pba = 0; 1532*0Sstevel@tonic-gate } 1533*0Sstevel@tonic-gate } 1534*0Sstevel@tonic-gate 1535*0Sstevel@tonic-gate /* 1536*0Sstevel@tonic-gate * Return zero if the buffers are identical in length and content. 1537*0Sstevel@tonic-gate * This is used for comparing extension header buffers. 1538*0Sstevel@tonic-gate * Note that an extension header would be declared different 1539*0Sstevel@tonic-gate * even if all that changed was the next header value in that header i.e. 1540*0Sstevel@tonic-gate * what really changed is the next extension header. 1541*0Sstevel@tonic-gate */ 1542*0Sstevel@tonic-gate boolean_t 1543*0Sstevel@tonic-gate sctp_cmpbuf(void *a, uint_t alen, boolean_t b_valid, void *b, uint_t blen) 1544*0Sstevel@tonic-gate { 1545*0Sstevel@tonic-gate if (!b_valid) 1546*0Sstevel@tonic-gate blen = 0; 1547*0Sstevel@tonic-gate 1548*0Sstevel@tonic-gate if (alen != blen) 1549*0Sstevel@tonic-gate return (B_TRUE); 1550*0Sstevel@tonic-gate if (alen == 0) 1551*0Sstevel@tonic-gate return (B_FALSE); /* Both zero length */ 1552*0Sstevel@tonic-gate return (bcmp(a, b, alen)); 1553*0Sstevel@tonic-gate } 1554*0Sstevel@tonic-gate 1555*0Sstevel@tonic-gate /* 1556*0Sstevel@tonic-gate * Preallocate memory for sctp_savebuf(). Returns B_TRUE if ok. 1557*0Sstevel@tonic-gate * Return B_FALSE if memory allocation fails - don't change any state! 1558*0Sstevel@tonic-gate */ 1559*0Sstevel@tonic-gate boolean_t 1560*0Sstevel@tonic-gate sctp_allocbuf(void **dstp, uint_t *dstlenp, boolean_t src_valid, 1561*0Sstevel@tonic-gate void *src, uint_t srclen) 1562*0Sstevel@tonic-gate { 1563*0Sstevel@tonic-gate void *dst; 1564*0Sstevel@tonic-gate 1565*0Sstevel@tonic-gate if (!src_valid) 1566*0Sstevel@tonic-gate srclen = 0; 1567*0Sstevel@tonic-gate 1568*0Sstevel@tonic-gate ASSERT(*dstlenp == 0); 1569*0Sstevel@tonic-gate if (src != NULL && srclen != 0) { 1570*0Sstevel@tonic-gate dst = mi_zalloc(srclen); 1571*0Sstevel@tonic-gate if (dst == NULL) 1572*0Sstevel@tonic-gate return (B_FALSE); 1573*0Sstevel@tonic-gate } else { 1574*0Sstevel@tonic-gate dst = NULL; 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate if (*dstp != NULL) { 1577*0Sstevel@tonic-gate mi_free(*dstp); 1578*0Sstevel@tonic-gate *dstp = NULL; 1579*0Sstevel@tonic-gate *dstlenp = 0; 1580*0Sstevel@tonic-gate } 1581*0Sstevel@tonic-gate *dstp = dst; 1582*0Sstevel@tonic-gate if (dst != NULL) 1583*0Sstevel@tonic-gate *dstlenp = srclen; 1584*0Sstevel@tonic-gate else 1585*0Sstevel@tonic-gate *dstlenp = 0; 1586*0Sstevel@tonic-gate return (B_TRUE); 1587*0Sstevel@tonic-gate } 1588*0Sstevel@tonic-gate 1589*0Sstevel@tonic-gate /* 1590*0Sstevel@tonic-gate * Replace what is in *dst, *dstlen with the source. 1591*0Sstevel@tonic-gate * Assumes sctp_allocbuf has already been called. 1592*0Sstevel@tonic-gate */ 1593*0Sstevel@tonic-gate void 1594*0Sstevel@tonic-gate sctp_savebuf(void **dstp, uint_t *dstlenp, boolean_t src_valid, 1595*0Sstevel@tonic-gate void *src, uint_t srclen) 1596*0Sstevel@tonic-gate { 1597*0Sstevel@tonic-gate if (!src_valid) 1598*0Sstevel@tonic-gate srclen = 0; 1599*0Sstevel@tonic-gate 1600*0Sstevel@tonic-gate ASSERT(*dstlenp == srclen); 1601*0Sstevel@tonic-gate if (src != NULL && srclen != 0) { 1602*0Sstevel@tonic-gate bcopy(src, *dstp, srclen); 1603*0Sstevel@tonic-gate } 1604*0Sstevel@tonic-gate } 1605*0Sstevel@tonic-gate 1606*0Sstevel@tonic-gate static void 1607*0Sstevel@tonic-gate sctp_init_faddr(sctp_t *sctp, sctp_faddr_t *fp, in6_addr_t *addr) 1608*0Sstevel@tonic-gate { 1609*0Sstevel@tonic-gate bcopy(addr, &fp->faddr, sizeof (*addr)); 1610*0Sstevel@tonic-gate if (IN6_IS_ADDR_V4MAPPED(addr)) { 1611*0Sstevel@tonic-gate fp->isv4 = 1; 1612*0Sstevel@tonic-gate /* Make sure that sfa_pmss is a multiple of SCTP_ALIGN. */ 1613*0Sstevel@tonic-gate fp->sfa_pmss = (sctp_initial_mtu - sctp->sctp_hdr_len) & 1614*0Sstevel@tonic-gate ~(SCTP_ALIGN - 1); 1615*0Sstevel@tonic-gate } else { 1616*0Sstevel@tonic-gate fp->isv4 = 0; 1617*0Sstevel@tonic-gate fp->sfa_pmss = (sctp_initial_mtu - sctp->sctp_hdr6_len) & 1618*0Sstevel@tonic-gate ~(SCTP_ALIGN - 1); 1619*0Sstevel@tonic-gate } 1620*0Sstevel@tonic-gate fp->cwnd = sctp_slow_start_initial * fp->sfa_pmss; 1621*0Sstevel@tonic-gate fp->rto = MIN(sctp->sctp_rto_initial, sctp->sctp_init_rto_max); 1622*0Sstevel@tonic-gate fp->srtt = -1; 1623*0Sstevel@tonic-gate fp->rtt_updates = 0; 1624*0Sstevel@tonic-gate fp->strikes = 0; 1625*0Sstevel@tonic-gate fp->max_retr = sctp->sctp_pp_max_rxt; 1626*0Sstevel@tonic-gate /* Mark it as not confirmed. */ 1627*0Sstevel@tonic-gate fp->state = SCTP_FADDRS_UNCONFIRMED; 1628*0Sstevel@tonic-gate fp->hb_interval = sctp->sctp_hb_interval; 1629*0Sstevel@tonic-gate fp->ssthresh = sctp_initial_ssthresh; 1630*0Sstevel@tonic-gate fp->suna = 0; 1631*0Sstevel@tonic-gate fp->pba = 0; 1632*0Sstevel@tonic-gate fp->acked = 0; 1633*0Sstevel@tonic-gate fp->lastactive = lbolt64; 1634*0Sstevel@tonic-gate fp->timer_mp = NULL; 1635*0Sstevel@tonic-gate fp->hb_pending = B_FALSE; 1636*0Sstevel@tonic-gate fp->timer_running = 0; 1637*0Sstevel@tonic-gate fp->df = 1; 1638*0Sstevel@tonic-gate fp->pmtu_discovered = 0; 1639*0Sstevel@tonic-gate fp->rc_timer_mp = NULL; 1640*0Sstevel@tonic-gate fp->rc_timer_running = 0; 1641*0Sstevel@tonic-gate fp->next = NULL; 1642*0Sstevel@tonic-gate fp->ire = NULL; 1643*0Sstevel@tonic-gate fp->T3expire = 0; 1644*0Sstevel@tonic-gate (void) random_get_pseudo_bytes((uint8_t *)&fp->hb_secret, 1645*0Sstevel@tonic-gate sizeof (fp->hb_secret)); 1646*0Sstevel@tonic-gate fp->hb_expiry = lbolt64; 1647*0Sstevel@tonic-gate 1648*0Sstevel@tonic-gate sctp_ire2faddr(sctp, fp); 1649*0Sstevel@tonic-gate } 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate /*ARGSUSED*/ 1652*0Sstevel@tonic-gate static void 1653*0Sstevel@tonic-gate faddr_destructor(void *buf, void *cdrarg) 1654*0Sstevel@tonic-gate { 1655*0Sstevel@tonic-gate sctp_faddr_t *fp = buf; 1656*0Sstevel@tonic-gate 1657*0Sstevel@tonic-gate ASSERT(fp->timer_mp == NULL); 1658*0Sstevel@tonic-gate ASSERT(fp->timer_running == 0); 1659*0Sstevel@tonic-gate 1660*0Sstevel@tonic-gate ASSERT(fp->rc_timer_mp == NULL); 1661*0Sstevel@tonic-gate ASSERT(fp->rc_timer_running == 0); 1662*0Sstevel@tonic-gate } 1663*0Sstevel@tonic-gate 1664*0Sstevel@tonic-gate void 1665*0Sstevel@tonic-gate sctp_faddr_init() 1666*0Sstevel@tonic-gate { 1667*0Sstevel@tonic-gate sctp_kmem_faddr_cache = kmem_cache_create("sctp_faddr_cache", 1668*0Sstevel@tonic-gate sizeof (sctp_faddr_t), 0, NULL, faddr_destructor, 1669*0Sstevel@tonic-gate NULL, NULL, NULL, 0); 1670*0Sstevel@tonic-gate } 1671*0Sstevel@tonic-gate 1672*0Sstevel@tonic-gate void 1673*0Sstevel@tonic-gate sctp_faddr_fini() 1674*0Sstevel@tonic-gate { 1675*0Sstevel@tonic-gate kmem_cache_destroy(sctp_kmem_faddr_cache); 1676*0Sstevel@tonic-gate } 1677