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/cmn_err.h> 33*0Sstevel@tonic-gate #include <sys/strsubr.h> 34*0Sstevel@tonic-gate #include <sys/strsun.h> 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #include <netinet/in.h> 37*0Sstevel@tonic-gate #include <netinet/ip6.h> 38*0Sstevel@tonic-gate 39*0Sstevel@tonic-gate #include <inet/common.h> 40*0Sstevel@tonic-gate #include <inet/ip.h> 41*0Sstevel@tonic-gate #include <inet/mib2.h> 42*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 43*0Sstevel@tonic-gate #include "sctp_impl.h" 44*0Sstevel@tonic-gate #include "sctp_asconf.h" 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate /* Timer block states. */ 47*0Sstevel@tonic-gate typedef enum { 48*0Sstevel@tonic-gate SCTP_TB_RUNNING = 1, 49*0Sstevel@tonic-gate SCTP_TB_IDLE, 50*0Sstevel@tonic-gate /* Could not stop/free before mblk got queued */ 51*0Sstevel@tonic-gate SCTP_TB_RESCHED, /* sctp_tb_time_left contains tick count */ 52*0Sstevel@tonic-gate SCTP_TB_CANCELLED, 53*0Sstevel@tonic-gate SCTP_TB_TO_BE_FREED 54*0Sstevel@tonic-gate } timer_block_state; 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate typedef struct sctp_tb_s { 57*0Sstevel@tonic-gate timer_block_state sctp_tb_state; 58*0Sstevel@tonic-gate timeout_id_t sctp_tb_tid; 59*0Sstevel@tonic-gate mblk_t *sctp_tb_mp; 60*0Sstevel@tonic-gate clock_t sctp_tb_time_left; 61*0Sstevel@tonic-gate } sctp_tb_t; 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate static void sctp_timer_fire(sctp_tb_t *); 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate /* 66*0Sstevel@tonic-gate * sctp_timer mechanism. 67*0Sstevel@tonic-gate * 68*0Sstevel@tonic-gate * Each timer is represented by a timer mblk. When the 69*0Sstevel@tonic-gate * timer fires, and the sctp_t is busy, the timer mblk will be put on 70*0Sstevel@tonic-gate * the associated sctp_t timer queue so that it can be executed when 71*0Sstevel@tonic-gate * the thread holding the lock on the sctp_t is done with its job. 72*0Sstevel@tonic-gate * 73*0Sstevel@tonic-gate * Note that there is no lock to protect the timer mblk state. The reason 74*0Sstevel@tonic-gate * is that the timer state can only be changed by a thread holding the 75*0Sstevel@tonic-gate * lock on the sctp_t. 76*0Sstevel@tonic-gate * 77*0Sstevel@tonic-gate * The interface consists of 4 entry points: 78*0Sstevel@tonic-gate * sctp_timer_alloc - create a timer mblk 79*0Sstevel@tonic-gate * sctp_timer_free - free a timer mblk 80*0Sstevel@tonic-gate * sctp_timer - start, restart, stop the timer 81*0Sstevel@tonic-gate * sctp_timer_valid - called by sctp_process_recvq to verify that 82*0Sstevel@tonic-gate * the timer did indeed fire. 83*0Sstevel@tonic-gate */ 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate /* 87*0Sstevel@tonic-gate * Start, restart, stop the timer. 88*0Sstevel@tonic-gate * If "tim" is -1 the timer is stopped. 89*0Sstevel@tonic-gate * Otherwise, the timer is stopped if it is already running, and 90*0Sstevel@tonic-gate * set to fire tim clock ticks from now. 91*0Sstevel@tonic-gate */ 92*0Sstevel@tonic-gate void 93*0Sstevel@tonic-gate sctp_timer(sctp_t *sctp, mblk_t *mp, clock_t tim) 94*0Sstevel@tonic-gate { 95*0Sstevel@tonic-gate sctp_tb_t *sctp_tb; 96*0Sstevel@tonic-gate int state; 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate ASSERT(sctp != NULL && mp != NULL); 99*0Sstevel@tonic-gate ASSERT((mp->b_rptr - mp->b_datap->db_base) == sizeof (sctp_tb_t)); 100*0Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG); 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate sctp_tb = (sctp_tb_t *)mp->b_datap->db_base; 103*0Sstevel@tonic-gate if (tim >= 0) { 104*0Sstevel@tonic-gate state = sctp_tb->sctp_tb_state; 105*0Sstevel@tonic-gate sctp_tb->sctp_tb_time_left = tim; 106*0Sstevel@tonic-gate if (state == SCTP_TB_RUNNING) { 107*0Sstevel@tonic-gate if (untimeout(sctp_tb->sctp_tb_tid) < 0) { 108*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_RESCHED; 109*0Sstevel@tonic-gate /* sctp_timer_valid will start timer */ 110*0Sstevel@tonic-gate return; 111*0Sstevel@tonic-gate } 112*0Sstevel@tonic-gate } else if (state != SCTP_TB_IDLE) { 113*0Sstevel@tonic-gate ASSERT(state != SCTP_TB_TO_BE_FREED); 114*0Sstevel@tonic-gate if (state == SCTP_TB_CANCELLED) { 115*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_RESCHED; 116*0Sstevel@tonic-gate /* sctp_timer_valid will start timer */ 117*0Sstevel@tonic-gate return; 118*0Sstevel@tonic-gate } 119*0Sstevel@tonic-gate if (state == SCTP_TB_RESCHED) { 120*0Sstevel@tonic-gate /* sctp_timer_valid will start timer */ 121*0Sstevel@tonic-gate return; 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate } else { 124*0Sstevel@tonic-gate SCTP_REFHOLD(sctp); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_RUNNING; 127*0Sstevel@tonic-gate sctp_tb->sctp_tb_tid = 128*0Sstevel@tonic-gate timeout((pfv_t)sctp_timer_fire, sctp_tb, tim); 129*0Sstevel@tonic-gate return; 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate switch (tim) { 132*0Sstevel@tonic-gate case -1: 133*0Sstevel@tonic-gate sctp_timer_stop(mp); 134*0Sstevel@tonic-gate break; 135*0Sstevel@tonic-gate default: 136*0Sstevel@tonic-gate ASSERT(0); 137*0Sstevel@tonic-gate break; 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate } 140*0Sstevel@tonic-gate 141*0Sstevel@tonic-gate /* 142*0Sstevel@tonic-gate * sctp_timer_alloc is called by sctp_init to allocate and initialize a 143*0Sstevel@tonic-gate * sctp timer. 144*0Sstevel@tonic-gate * 145*0Sstevel@tonic-gate * Allocate an M_PCSIG timer message. The space between db_base and 146*0Sstevel@tonic-gate * b_rptr is used by the sctp_timer mechanism, and after b_rptr there is 147*0Sstevel@tonic-gate * space for sctpt_t. 148*0Sstevel@tonic-gate */ 149*0Sstevel@tonic-gate mblk_t * 150*0Sstevel@tonic-gate sctp_timer_alloc(sctp_t *sctp, pfv_t func) 151*0Sstevel@tonic-gate { 152*0Sstevel@tonic-gate mblk_t *mp; 153*0Sstevel@tonic-gate sctp_tb_t *sctp_tb; 154*0Sstevel@tonic-gate sctpt_t *sctpt; 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate if ((mp = allocb(sizeof (sctp_t) + sizeof (sctp_tb_t), BPRI_HI))) { 157*0Sstevel@tonic-gate mp->b_datap->db_type = M_PCSIG; 158*0Sstevel@tonic-gate sctp_tb = (sctp_tb_t *)mp->b_datap->db_base; 159*0Sstevel@tonic-gate mp->b_rptr = (uchar_t *)&sctp_tb[1]; 160*0Sstevel@tonic-gate mp->b_wptr = mp->b_rptr + sizeof (sctpt_t); 161*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_IDLE; 162*0Sstevel@tonic-gate sctp_tb->sctp_tb_mp = mp; 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate sctpt = (sctpt_t *)mp->b_rptr; 165*0Sstevel@tonic-gate sctpt->sctpt_sctp = sctp; 166*0Sstevel@tonic-gate sctpt->sctpt_faddr = NULL; /* set when starting timer */ 167*0Sstevel@tonic-gate sctpt->sctpt_pfv = func; 168*0Sstevel@tonic-gate return (mp); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate return (NULL); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate /* 174*0Sstevel@tonic-gate * timeout() callback function. 175*0Sstevel@tonic-gate * Put the message on the process control block's queue. 176*0Sstevel@tonic-gate * If the timer is stopped or freed after 177*0Sstevel@tonic-gate * it has fired then sctp_timer() and sctp_timer_valid() will clean 178*0Sstevel@tonic-gate * things up. 179*0Sstevel@tonic-gate */ 180*0Sstevel@tonic-gate static void 181*0Sstevel@tonic-gate sctp_timer_fire(sctp_tb_t *sctp_tb) 182*0Sstevel@tonic-gate { 183*0Sstevel@tonic-gate mblk_t *mp; 184*0Sstevel@tonic-gate sctp_t *sctp; 185*0Sstevel@tonic-gate sctpt_t *sctpt; 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate mp = sctp_tb->sctp_tb_mp; 188*0Sstevel@tonic-gate ASSERT(sctp_tb == (sctp_tb_t *)mp->b_datap->db_base); 189*0Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG); 190*0Sstevel@tonic-gate 191*0Sstevel@tonic-gate sctpt = (sctpt_t *)mp->b_rptr; 192*0Sstevel@tonic-gate sctp = sctpt->sctpt_sctp; 193*0Sstevel@tonic-gate ASSERT(sctp != NULL); 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate mutex_enter(&sctp->sctp_lock); 196*0Sstevel@tonic-gate if (sctp->sctp_running) { 197*0Sstevel@tonic-gate /* 198*0Sstevel@tonic-gate * Put the timer mblk to the special sctp_timer_mp list. 199*0Sstevel@tonic-gate * This timer will be handled when the thread using this 200*0Sstevel@tonic-gate * SCTP is done with its job. 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate if (sctp->sctp_timer_mp == NULL) { 203*0Sstevel@tonic-gate SCTP_REFHOLD(sctp); 204*0Sstevel@tonic-gate sctp->sctp_timer_mp = mp; 205*0Sstevel@tonic-gate } else { 206*0Sstevel@tonic-gate linkb(sctp->sctp_timer_mp, mp); 207*0Sstevel@tonic-gate } 208*0Sstevel@tonic-gate mp->b_cont = NULL; 209*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_lock); 210*0Sstevel@tonic-gate } else { 211*0Sstevel@tonic-gate sctp->sctp_running = B_TRUE; 212*0Sstevel@tonic-gate mutex_exit(&sctp->sctp_lock); 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate sctp_timer_call(sctp, mp); 215*0Sstevel@tonic-gate WAKE_SCTP(sctp); 216*0Sstevel@tonic-gate sctp_process_sendq(sctp); 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate SCTP_REFRELE(sctp); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate /* 222*0Sstevel@tonic-gate * Logically free a timer mblk (that might have a pending timeout().) 223*0Sstevel@tonic-gate * If the timer has fired and the mblk has been put on the queue then 224*0Sstevel@tonic-gate * sctp_timer_valid will free the mblk. 225*0Sstevel@tonic-gate */ 226*0Sstevel@tonic-gate void 227*0Sstevel@tonic-gate sctp_timer_free(mblk_t *mp) 228*0Sstevel@tonic-gate { 229*0Sstevel@tonic-gate sctp_tb_t *sctp_tb; 230*0Sstevel@tonic-gate int state; 231*0Sstevel@tonic-gate sctpt_t *sctpt; 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate ASSERT(mp != NULL); 234*0Sstevel@tonic-gate ASSERT((mp->b_rptr - mp->b_datap->db_base) == sizeof (sctp_tb_t)); 235*0Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG); 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate sctp_tb = (sctp_tb_t *)mp->b_datap->db_base; 238*0Sstevel@tonic-gate state = sctp_tb->sctp_tb_state; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate dprint(5, ("sctp_timer_free %p state %d\n", mp, state)); 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate if (state == SCTP_TB_RUNNING) { 243*0Sstevel@tonic-gate if (untimeout(sctp_tb->sctp_tb_tid) < 0) { 244*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_TO_BE_FREED; 245*0Sstevel@tonic-gate /* sctp_timer_valid will free the mblk */ 246*0Sstevel@tonic-gate return; 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate sctpt = (sctpt_t *)mp->b_rptr; 249*0Sstevel@tonic-gate SCTP_REFRELE(sctpt->sctpt_sctp); 250*0Sstevel@tonic-gate } else if (state != SCTP_TB_IDLE) { 251*0Sstevel@tonic-gate ASSERT(state != SCTP_TB_TO_BE_FREED); 252*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_TO_BE_FREED; 253*0Sstevel@tonic-gate /* sctp_timer_valid will free the mblk */ 254*0Sstevel@tonic-gate return; 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate freeb(mp); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * Called from sctp_timer(,,-1) 261*0Sstevel@tonic-gate */ 262*0Sstevel@tonic-gate void 263*0Sstevel@tonic-gate sctp_timer_stop(mblk_t *mp) 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate sctp_tb_t *sctp_tb; 266*0Sstevel@tonic-gate int state; 267*0Sstevel@tonic-gate sctpt_t *sctpt; 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate ASSERT(mp != NULL); 270*0Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG); 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate sctp_tb = (sctp_tb_t *)mp->b_datap->db_base; 273*0Sstevel@tonic-gate state = sctp_tb->sctp_tb_state; 274*0Sstevel@tonic-gate 275*0Sstevel@tonic-gate dprint(5, ("sctp_timer_stop %p %d\n", mp, state)); 276*0Sstevel@tonic-gate 277*0Sstevel@tonic-gate if (state == SCTP_TB_RUNNING) { 278*0Sstevel@tonic-gate if (untimeout(sctp_tb->sctp_tb_tid) < 0) { 279*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_CANCELLED; 280*0Sstevel@tonic-gate } else { 281*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_IDLE; 282*0Sstevel@tonic-gate sctpt = (sctpt_t *)mp->b_rptr; 283*0Sstevel@tonic-gate SCTP_REFRELE(sctpt->sctpt_sctp); 284*0Sstevel@tonic-gate } 285*0Sstevel@tonic-gate } else if (state == SCTP_TB_RESCHED) { 286*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_CANCELLED; 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate /* 291*0Sstevel@tonic-gate * The user of the sctp_timer mechanism is required to call 292*0Sstevel@tonic-gate * sctp_timer_valid() for each M_PCSIG message processed in the 293*0Sstevel@tonic-gate * service procedures. 294*0Sstevel@tonic-gate * sctp_timer_valid will return "true" if the timer actually did fire. 295*0Sstevel@tonic-gate */ 296*0Sstevel@tonic-gate 297*0Sstevel@tonic-gate static boolean_t 298*0Sstevel@tonic-gate sctp_timer_valid(mblk_t *mp) 299*0Sstevel@tonic-gate { 300*0Sstevel@tonic-gate sctp_tb_t *sctp_tb; 301*0Sstevel@tonic-gate int state; 302*0Sstevel@tonic-gate sctpt_t *sctpt; 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate ASSERT(mp != NULL); 305*0Sstevel@tonic-gate ASSERT(mp->b_datap->db_type == M_PCSIG); 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate sctp_tb = (sctp_tb_t *)DB_BASE(mp); 308*0Sstevel@tonic-gate sctpt = (sctpt_t *)mp->b_rptr; 309*0Sstevel@tonic-gate state = sctp_tb->sctp_tb_state; 310*0Sstevel@tonic-gate if (state != SCTP_TB_RUNNING) { 311*0Sstevel@tonic-gate ASSERT(state != SCTP_TB_IDLE); 312*0Sstevel@tonic-gate if (state == SCTP_TB_TO_BE_FREED) { 313*0Sstevel@tonic-gate /* 314*0Sstevel@tonic-gate * sctp_timer_free was called after the message 315*0Sstevel@tonic-gate * was putq'ed. 316*0Sstevel@tonic-gate */ 317*0Sstevel@tonic-gate freeb(mp); 318*0Sstevel@tonic-gate return (B_FALSE); 319*0Sstevel@tonic-gate } 320*0Sstevel@tonic-gate if (state == SCTP_TB_CANCELLED) { 321*0Sstevel@tonic-gate /* The timer was stopped after the mblk was putq'ed */ 322*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_IDLE; 323*0Sstevel@tonic-gate return (B_FALSE); 324*0Sstevel@tonic-gate } 325*0Sstevel@tonic-gate if (state == SCTP_TB_RESCHED) { 326*0Sstevel@tonic-gate /* 327*0Sstevel@tonic-gate * The timer was stopped and then restarted after 328*0Sstevel@tonic-gate * the mblk was putq'ed. 329*0Sstevel@tonic-gate * sctp_tb_time_left contains the number of ticks that 330*0Sstevel@tonic-gate * the timer was restarted with. 331*0Sstevel@tonic-gate * The sctp will not be disapper between the time 332*0Sstevel@tonic-gate * the sctpt_t is marked SCTP_TB_RESCHED and when 333*0Sstevel@tonic-gate * we get here as sctp_add_recvq() does a refhold. 334*0Sstevel@tonic-gate */ 335*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_RUNNING; 336*0Sstevel@tonic-gate sctp_tb->sctp_tb_tid = timeout((pfv_t)sctp_timer_fire, 337*0Sstevel@tonic-gate sctp_tb, sctp_tb->sctp_tb_time_left); 338*0Sstevel@tonic-gate SCTP_REFHOLD(sctpt->sctpt_sctp); 339*0Sstevel@tonic-gate return (B_FALSE); 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate } 342*0Sstevel@tonic-gate sctp_tb->sctp_tb_state = SCTP_TB_IDLE; 343*0Sstevel@tonic-gate return (B_TRUE); 344*0Sstevel@tonic-gate } 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate /* 347*0Sstevel@tonic-gate * The SCTP timer call. Calls sctp_timer_valid() to verify whether 348*0Sstevel@tonic-gate * timer was cancelled or not. 349*0Sstevel@tonic-gate */ 350*0Sstevel@tonic-gate void 351*0Sstevel@tonic-gate sctp_timer_call(sctp_t *sctp, mblk_t *mp) 352*0Sstevel@tonic-gate { 353*0Sstevel@tonic-gate sctpt_t *sctpt = (sctpt_t *)mp->b_rptr; 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate if (sctp_timer_valid(mp)) { 356*0Sstevel@tonic-gate (*sctpt->sctpt_pfv)(sctp, sctpt->sctpt_faddr); 357*0Sstevel@tonic-gate } 358*0Sstevel@tonic-gate } 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate /* 361*0Sstevel@tonic-gate * Delayed ack 362*0Sstevel@tonic-gate */ 363*0Sstevel@tonic-gate void 364*0Sstevel@tonic-gate sctp_ack_timer(sctp_t *sctp) 365*0Sstevel@tonic-gate { 366*0Sstevel@tonic-gate sctp->sctp_ack_timer_running = 0; 367*0Sstevel@tonic-gate sctp->sctp_sack_toggle = 2; 368*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpOutAckDelayed); 369*0Sstevel@tonic-gate sctp_sack(sctp, NULL); 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* 373*0Sstevel@tonic-gate * Peer address heartbeat timer handler 374*0Sstevel@tonic-gate */ 375*0Sstevel@tonic-gate void 376*0Sstevel@tonic-gate sctp_heartbeat_timer(sctp_t *sctp) 377*0Sstevel@tonic-gate { 378*0Sstevel@tonic-gate sctp_faddr_t *fp; 379*0Sstevel@tonic-gate int64_t now; 380*0Sstevel@tonic-gate int64_t earliest_expiry; 381*0Sstevel@tonic-gate int cnt; 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate if (sctp->sctp_strikes >= sctp->sctp_pa_max_rxt) { 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * If there is a peer address with no strikes, 386*0Sstevel@tonic-gate * don't give up yet. If enough other peer 387*0Sstevel@tonic-gate * address are down, we could otherwise fail 388*0Sstevel@tonic-gate * the association prematurely. This is a 389*0Sstevel@tonic-gate * byproduct of our aggressive probe approach 390*0Sstevel@tonic-gate * when a heartbeat fails to connect. We may 391*0Sstevel@tonic-gate * wish to revisit this... 392*0Sstevel@tonic-gate */ 393*0Sstevel@tonic-gate if (!sctp_is_a_faddr_clean(sctp)) { 394*0Sstevel@tonic-gate /* time to give up */ 395*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 396*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimHeartBeatDrop); 397*0Sstevel@tonic-gate sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL); 398*0Sstevel@tonic-gate sctp_clean_death(sctp, sctp->sctp_client_errno ? 399*0Sstevel@tonic-gate sctp->sctp_client_errno : ETIMEDOUT); 400*0Sstevel@tonic-gate return; 401*0Sstevel@tonic-gate } 402*0Sstevel@tonic-gate } 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate /* Only send heartbeats in the established state */ 405*0Sstevel@tonic-gate if (sctp->sctp_state != SCTPS_ESTABLISHED) { 406*0Sstevel@tonic-gate dprint(5, ("sctp_heartbeat_timer: not in ESTABLISHED\n")); 407*0Sstevel@tonic-gate return; 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate now = lbolt64; 411*0Sstevel@tonic-gate earliest_expiry = 0; 412*0Sstevel@tonic-gate cnt = sctp_maxburst; 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate /* 415*0Sstevel@tonic-gate * Walk through all faddrs. Since the timer should run infrequently 416*0Sstevel@tonic-gate * and the number of peer addresses should not be big, this should 417*0Sstevel@tonic-gate * be OK. 418*0Sstevel@tonic-gate */ 419*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 420*0Sstevel@tonic-gate /* 421*0Sstevel@tonic-gate * Don't send heartbeat to this address if 422*0Sstevel@tonic-gate * 1. it is not reachable OR 423*0Sstevel@tonic-gate * 2. hb_interval == 0 and the address has been confirmed. 424*0Sstevel@tonic-gate */ 425*0Sstevel@tonic-gate if (fp->state == SCTP_FADDRS_UNREACH || 426*0Sstevel@tonic-gate (fp->hb_interval == 0 && 427*0Sstevel@tonic-gate fp->state != SCTP_FADDRS_UNCONFIRMED)) { 428*0Sstevel@tonic-gate continue; 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate /* 432*0Sstevel@tonic-gate * The heartbeat timer is expired. If the address is dead, 433*0Sstevel@tonic-gate * we still send heartbeat to it in case it becomes alive 434*0Sstevel@tonic-gate * again. But we will only send once every hb_interval. 435*0Sstevel@tonic-gate * 436*0Sstevel@tonic-gate * If the address is alive and there is a hearbeat pending, 437*0Sstevel@tonic-gate * resend the heartbeat and start exponential backoff on the 438*0Sstevel@tonic-gate * heartbeat timeout value. If there is no heartbeat pending, 439*0Sstevel@tonic-gate * just send out one. 440*0Sstevel@tonic-gate */ 441*0Sstevel@tonic-gate if (now >= fp->hb_expiry) { 442*0Sstevel@tonic-gate if (fp->hb_pending) { 443*0Sstevel@tonic-gate /* 444*0Sstevel@tonic-gate * If an address is not confirmed, no need 445*0Sstevel@tonic-gate * to bump the overall counter as it doesn't 446*0Sstevel@tonic-gate * matter as we will not use it to send data 447*0Sstevel@tonic-gate * and it should not affect the association. 448*0Sstevel@tonic-gate */ 449*0Sstevel@tonic-gate switch (fp->state) { 450*0Sstevel@tonic-gate case SCTP_FADDRS_ALIVE: 451*0Sstevel@tonic-gate sctp->sctp_strikes++; 452*0Sstevel@tonic-gate /* FALLTHRU */ 453*0Sstevel@tonic-gate case SCTP_FADDRS_UNCONFIRMED: 454*0Sstevel@tonic-gate /* 455*0Sstevel@tonic-gate * Retransmission implies that RTO 456*0Sstevel@tonic-gate * is probably not correct. 457*0Sstevel@tonic-gate */ 458*0Sstevel@tonic-gate fp->rtt_updates = 0; 459*0Sstevel@tonic-gate fp->strikes++; 460*0Sstevel@tonic-gate if (fp->strikes > fp->max_retr) { 461*0Sstevel@tonic-gate if (sctp_faddr_dead(sctp, fp, 462*0Sstevel@tonic-gate SCTP_FADDRS_DOWN) == -1) { 463*0Sstevel@tonic-gate /* Assoc is dead */ 464*0Sstevel@tonic-gate return; 465*0Sstevel@tonic-gate } 466*0Sstevel@tonic-gate /* 467*0Sstevel@tonic-gate * Addr is down; keep initial 468*0Sstevel@tonic-gate * RTO 469*0Sstevel@tonic-gate */ 470*0Sstevel@tonic-gate fp->rto = 471*0Sstevel@tonic-gate sctp->sctp_rto_initial; 472*0Sstevel@tonic-gate goto dead_addr; 473*0Sstevel@tonic-gate } else { 474*0Sstevel@tonic-gate SCTP_CALC_RXT(fp, 475*0Sstevel@tonic-gate sctp->sctp_rto_max); 476*0Sstevel@tonic-gate fp->hb_expiry = now + fp->rto; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate break; 479*0Sstevel@tonic-gate case SCTP_FADDRS_DOWN: 480*0Sstevel@tonic-gate dead_addr: 481*0Sstevel@tonic-gate fp->hb_expiry = now + SET_HB_INTVL(fp); 482*0Sstevel@tonic-gate break; 483*0Sstevel@tonic-gate default: 484*0Sstevel@tonic-gate continue; 485*0Sstevel@tonic-gate } 486*0Sstevel@tonic-gate } else { 487*0Sstevel@tonic-gate fp->hb_expiry = now + fp->rto; 488*0Sstevel@tonic-gate } 489*0Sstevel@tonic-gate /* 490*0Sstevel@tonic-gate * Note that the total number of heartbeat we can send 491*0Sstevel@tonic-gate * out simultaneously is limited by sctp_maxburst. If 492*0Sstevel@tonic-gate * the limit is exceeded, we need to wait for the next 493*0Sstevel@tonic-gate * timeout to send them. This should only happen if 494*0Sstevel@tonic-gate * there is unconfirmed address. Note that hb_pending 495*0Sstevel@tonic-gate * is set in sctp_send_heartbeat(). So if a heartbeat 496*0Sstevel@tonic-gate * is not sent, it will not affect the state of the 497*0Sstevel@tonic-gate * peer address. 498*0Sstevel@tonic-gate */ 499*0Sstevel@tonic-gate if (fp->state != SCTP_FADDRS_UNCONFIRMED || cnt-- > 0) 500*0Sstevel@tonic-gate sctp_send_heartbeat(sctp, fp); 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate if (fp->hb_expiry < earliest_expiry || earliest_expiry == 0) 503*0Sstevel@tonic-gate earliest_expiry = fp->hb_expiry; 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate if (sctp->sctp_autoclose != 0) { 506*0Sstevel@tonic-gate int64_t expire; 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate expire = sctp->sctp_active + sctp->sctp_autoclose; 509*0Sstevel@tonic-gate 510*0Sstevel@tonic-gate if (expire <= now) { 511*0Sstevel@tonic-gate dprint(3, ("sctp_heartbeat_timer: autoclosing\n")); 512*0Sstevel@tonic-gate sctp_send_shutdown(sctp, 0); 513*0Sstevel@tonic-gate return; 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate if (expire < earliest_expiry || earliest_expiry == 0) 516*0Sstevel@tonic-gate earliest_expiry = expire; 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate earliest_expiry -= now; 520*0Sstevel@tonic-gate if (earliest_expiry < 0) 521*0Sstevel@tonic-gate earliest_expiry = 1; 522*0Sstevel@tonic-gate sctp_timer(sctp, sctp->sctp_heartbeat_mp, earliest_expiry); 523*0Sstevel@tonic-gate } 524*0Sstevel@tonic-gate 525*0Sstevel@tonic-gate void 526*0Sstevel@tonic-gate sctp_rexmit_timer(sctp_t *sctp, sctp_faddr_t *fp) 527*0Sstevel@tonic-gate { 528*0Sstevel@tonic-gate mblk_t *mp; 529*0Sstevel@tonic-gate uint32_t rto_max = sctp->sctp_rto_max; 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate ASSERT(fp != NULL); 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate dprint(3, ("sctp_timer: faddr=%x:%x:%x:%x\n", 534*0Sstevel@tonic-gate SCTP_PRINTADDR(fp->faddr))); 535*0Sstevel@tonic-gate 536*0Sstevel@tonic-gate fp->timer_running = 0; 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate /* Check is we've reached the max for retries */ 539*0Sstevel@tonic-gate if (sctp->sctp_state < SCTPS_ESTABLISHED) { 540*0Sstevel@tonic-gate if (fp->strikes >= sctp->sctp_max_init_rxt) { 541*0Sstevel@tonic-gate /* time to give up */ 542*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 543*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimRetransDrop); 544*0Sstevel@tonic-gate sctp_assoc_event(sctp, SCTP_CANT_STR_ASSOC, 0, NULL); 545*0Sstevel@tonic-gate sctp_clean_death(sctp, sctp->sctp_client_errno ? 546*0Sstevel@tonic-gate sctp->sctp_client_errno : ETIMEDOUT); 547*0Sstevel@tonic-gate return; 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate } else if (sctp->sctp_state >= SCTPS_ESTABLISHED) { 550*0Sstevel@tonic-gate if (sctp->sctp_strikes >= sctp->sctp_pa_max_rxt) { 551*0Sstevel@tonic-gate /* time to give up */ 552*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 553*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimRetransDrop); 554*0Sstevel@tonic-gate sctp_assoc_event(sctp, SCTP_COMM_LOST, 0, NULL); 555*0Sstevel@tonic-gate sctp_clean_death(sctp, sctp->sctp_client_errno ? 556*0Sstevel@tonic-gate sctp->sctp_client_errno : ETIMEDOUT); 557*0Sstevel@tonic-gate return; 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate } 560*0Sstevel@tonic-gate 561*0Sstevel@tonic-gate if (fp->strikes >= fp->max_retr) { 562*0Sstevel@tonic-gate if (sctp_faddr_dead(sctp, fp, SCTP_FADDRS_DOWN) == -1) { 563*0Sstevel@tonic-gate return; 564*0Sstevel@tonic-gate } 565*0Sstevel@tonic-gate } 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate switch (sctp->sctp_state) { 568*0Sstevel@tonic-gate case SCTPS_ESTABLISHED: 569*0Sstevel@tonic-gate /* 570*0Sstevel@tonic-gate * Reset the heartbeat expiry time. We don't need a heartbeat 571*0Sstevel@tonic-gate * timer running if we are retransmitting. Otherwise, the drop 572*0Sstevel@tonic-gate * of heartbeat may just make this peer address to be marked 573*0Sstevel@tonic-gate * dead faster as fp->strikes is also increased for heartbeat. 574*0Sstevel@tonic-gate */ 575*0Sstevel@tonic-gate fp->hb_expiry = lbolt64 + SET_HB_INTVL(fp); 576*0Sstevel@tonic-gate fp->hb_pending = B_FALSE; 577*0Sstevel@tonic-gate 578*0Sstevel@tonic-gate /* FALLTHRU */ 579*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_PENDING: 580*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_RECEIVED: 581*0Sstevel@tonic-gate if (sctp->sctp_state == SCTPS_SHUTDOWN_RECEIVED) { 582*0Sstevel@tonic-gate (void) sctp_shutdown_received(sctp, NULL, 0, 1); 583*0Sstevel@tonic-gate } 584*0Sstevel@tonic-gate 585*0Sstevel@tonic-gate if (sctp->sctp_xmit_head == NULL && 586*0Sstevel@tonic-gate sctp->sctp_xmit_unsent == NULL) { 587*0Sstevel@tonic-gate /* Nothing to retransmit */ 588*0Sstevel@tonic-gate if (sctp->sctp_state == SCTPS_SHUTDOWN_PENDING) { 589*0Sstevel@tonic-gate sctp_send_shutdown(sctp, 1); 590*0Sstevel@tonic-gate } 591*0Sstevel@tonic-gate return; 592*0Sstevel@tonic-gate } 593*0Sstevel@tonic-gate 594*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimRetrans); 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate sctp_rexmit(sctp, fp); 597*0Sstevel@tonic-gate /* 598*0Sstevel@tonic-gate * sctp_rexmit() will increase the strikes and restart the 599*0Sstevel@tonic-gate * timer, so return here. 600*0Sstevel@tonic-gate */ 601*0Sstevel@tonic-gate return; 602*0Sstevel@tonic-gate case SCTPS_COOKIE_WAIT: 603*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_T1expire); 604*0Sstevel@tonic-gate rxmit_init: 605*0Sstevel@tonic-gate /* retransmit init */ 606*0Sstevel@tonic-gate mp = sctp_init_mp(sctp); 607*0Sstevel@tonic-gate if (mp != NULL) { 608*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimRetrans); 609*0Sstevel@tonic-gate sctp_add_sendq(sctp, mp); 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate rto_max = sctp->sctp_init_rto_max; 612*0Sstevel@tonic-gate break; 613*0Sstevel@tonic-gate case SCTPS_COOKIE_ECHOED: { 614*0Sstevel@tonic-gate ipha_t *iph; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_T1expire); 617*0Sstevel@tonic-gate if (sctp->sctp_cookie_mp == NULL) { 618*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_COOKIE_WAIT; 619*0Sstevel@tonic-gate goto rxmit_init; 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate mp = dupmsg(sctp->sctp_cookie_mp); 622*0Sstevel@tonic-gate if (mp == NULL) 623*0Sstevel@tonic-gate break; 624*0Sstevel@tonic-gate iph = (ipha_t *)mp->b_rptr; 625*0Sstevel@tonic-gate /* Reset the IP ident. */ 626*0Sstevel@tonic-gate if (IPH_HDR_VERSION(iph) == IPV4_VERSION) 627*0Sstevel@tonic-gate iph->ipha_ident = 0; 628*0Sstevel@tonic-gate sctp_add_sendq(sctp, mp); 629*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimRetrans); 630*0Sstevel@tonic-gate rto_max = sctp->sctp_init_rto_max; 631*0Sstevel@tonic-gate break; 632*0Sstevel@tonic-gate } 633*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_SENT: 634*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_T2expire); 635*0Sstevel@tonic-gate sctp_send_shutdown(sctp, 1); 636*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimRetrans); 637*0Sstevel@tonic-gate break; 638*0Sstevel@tonic-gate case SCTPS_SHUTDOWN_ACK_SENT: 639*0Sstevel@tonic-gate /* We shouldn't have any more outstanding data */ 640*0Sstevel@tonic-gate ASSERT(sctp->sctp_xmit_head == NULL); 641*0Sstevel@tonic-gate ASSERT(sctp->sctp_xmit_unsent == NULL); 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_T2expire); 644*0Sstevel@tonic-gate (void) sctp_shutdown_received(sctp, NULL, 0, 1); 645*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpTimRetrans); 646*0Sstevel@tonic-gate break; 647*0Sstevel@tonic-gate default: 648*0Sstevel@tonic-gate ASSERT(0); 649*0Sstevel@tonic-gate break; 650*0Sstevel@tonic-gate } 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate fp->strikes++; 653*0Sstevel@tonic-gate sctp->sctp_strikes++; 654*0Sstevel@tonic-gate SCTP_CALC_RXT(fp, rto_max); 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->rto); 657*0Sstevel@tonic-gate } 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate /* 660*0Sstevel@tonic-gate * RTO calculation. timesent and now are both in ms. 661*0Sstevel@tonic-gate */ 662*0Sstevel@tonic-gate void 663*0Sstevel@tonic-gate sctp_update_rtt(sctp_t *sctp, sctp_faddr_t *fp, clock_t delta) 664*0Sstevel@tonic-gate { 665*0Sstevel@tonic-gate int rtt; 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate /* Calculate the RTT in ms */ 668*0Sstevel@tonic-gate rtt = (int)delta; 669*0Sstevel@tonic-gate rtt = rtt > 0 ? rtt : 1; 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate dprint(5, ("sctp_update_rtt: fp = %p, rtt = %d\n", fp, rtt)); 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate /* Is this the first RTT measurement? */ 674*0Sstevel@tonic-gate if (fp->srtt == -1) { 675*0Sstevel@tonic-gate fp->srtt = rtt; 676*0Sstevel@tonic-gate fp->rttvar = rtt / 2; 677*0Sstevel@tonic-gate fp->rto = 3 * rtt; /* == rtt + 4 * rttvar ( == rtt / 2) */ 678*0Sstevel@tonic-gate } else { 679*0Sstevel@tonic-gate int abs; 680*0Sstevel@tonic-gate /* 681*0Sstevel@tonic-gate * Versions of the RTO equations that use fixed-point math. 682*0Sstevel@tonic-gate * alpha and beta are NOT tunable in this implementation, 683*0Sstevel@tonic-gate * and so are hard-coded in. alpha = 1/8, beta = 1/4. 684*0Sstevel@tonic-gate */ 685*0Sstevel@tonic-gate abs = fp->srtt - rtt; 686*0Sstevel@tonic-gate abs = abs >= 0 ? abs : -abs; 687*0Sstevel@tonic-gate fp->rttvar = (3 * fp->rttvar + abs) >> 2; 688*0Sstevel@tonic-gate fp->rttvar = fp->rttvar != 0 ? fp->rttvar : 1; 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate fp->srtt = (7 * fp->srtt + rtt) >> 3; 691*0Sstevel@tonic-gate fp->rto = fp->srtt + 4 * fp->rttvar; 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate dprint(5, ("sctp_update_rtt: srtt = %d, rttvar = %d, rto = %d\n", 695*0Sstevel@tonic-gate fp->srtt, fp->rttvar, fp->rto)); 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate /* Bound the RTO by configured min and max values */ 698*0Sstevel@tonic-gate if (fp->rto < sctp->sctp_rto_min) { 699*0Sstevel@tonic-gate fp->rto = sctp->sctp_rto_min; 700*0Sstevel@tonic-gate } 701*0Sstevel@tonic-gate if (fp->rto > sctp->sctp_rto_max) { 702*0Sstevel@tonic-gate fp->rto = sctp->sctp_rto_max; 703*0Sstevel@tonic-gate } 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate fp->rtt_updates++; 706*0Sstevel@tonic-gate } 707*0Sstevel@tonic-gate 708*0Sstevel@tonic-gate void 709*0Sstevel@tonic-gate sctp_free_faddr_timers(sctp_t *sctp) 710*0Sstevel@tonic-gate { 711*0Sstevel@tonic-gate sctp_faddr_t *fp; 712*0Sstevel@tonic-gate 713*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 714*0Sstevel@tonic-gate if (fp->timer_mp != NULL) { 715*0Sstevel@tonic-gate sctp_timer_free(fp->timer_mp); 716*0Sstevel@tonic-gate fp->timer_mp = NULL; 717*0Sstevel@tonic-gate fp->timer_running = 0; 718*0Sstevel@tonic-gate } 719*0Sstevel@tonic-gate if (fp->rc_timer_mp != NULL) { 720*0Sstevel@tonic-gate sctp_timer_free(fp->rc_timer_mp); 721*0Sstevel@tonic-gate fp->rc_timer_mp = NULL; 722*0Sstevel@tonic-gate fp->rc_timer_running = 0; 723*0Sstevel@tonic-gate } 724*0Sstevel@tonic-gate } 725*0Sstevel@tonic-gate } 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate void 728*0Sstevel@tonic-gate sctp_stop_faddr_timers(sctp_t *sctp) 729*0Sstevel@tonic-gate { 730*0Sstevel@tonic-gate sctp_faddr_t *fp; 731*0Sstevel@tonic-gate 732*0Sstevel@tonic-gate for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->next) { 733*0Sstevel@tonic-gate SCTP_FADDR_TIMER_STOP(fp); 734*0Sstevel@tonic-gate SCTP_FADDR_RC_TIMER_STOP(fp); 735*0Sstevel@tonic-gate } 736*0Sstevel@tonic-gate } 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate void 739*0Sstevel@tonic-gate sctp_process_timer(sctp_t *sctp) 740*0Sstevel@tonic-gate { 741*0Sstevel@tonic-gate mblk_t *mp; 742*0Sstevel@tonic-gate 743*0Sstevel@tonic-gate ASSERT(sctp->sctp_running); 744*0Sstevel@tonic-gate ASSERT(MUTEX_HELD(&sctp->sctp_lock)); 745*0Sstevel@tonic-gate while ((mp = sctp->sctp_timer_mp) != NULL) { 746*0Sstevel@tonic-gate ASSERT(DB_TYPE(mp) == M_PCSIG); 747*0Sstevel@tonic-gate /* 748*0Sstevel@tonic-gate * Since the timer mblk can be freed in sctp_timer_call(), 749*0Sstevel@tonic-gate * we need to grab the b_cont before that. 750*0Sstevel@tonic-gate */ 751*0Sstevel@tonic-gate sctp->sctp_timer_mp = mp->b_cont; 752*0Sstevel@tonic-gate mp->b_cont = NULL; 753*0Sstevel@tonic-gate sctp_timer_call(sctp, mp); 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate SCTP_REFRELE(sctp); 756*0Sstevel@tonic-gate } 757