1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/stream.h> 29 #include <sys/cmn_err.h> 30 #define _SUN_TPI_VERSION 2 31 #include <sys/tihdr.h> 32 #include <sys/ddi.h> 33 #include <sys/sunddi.h> 34 #include <sys/tsol/tndb.h> 35 36 #include <netinet/in.h> 37 38 #include <inet/common.h> 39 #include <inet/ip.h> 40 #include <inet/mib2.h> 41 #include <inet/snmpcom.h> 42 #include <inet/kstatcom.h> 43 #include <inet/ipclassifier.h> 44 #include "sctp_impl.h" 45 #include "sctp_addr.h" 46 47 static int sctp_snmp_state(sctp_t *sctp); 48 49 50 static int 51 sctp_kstat_update(kstat_t *kp, int rw) 52 { 53 sctp_named_kstat_t *sctpkp; 54 sctp_t *sctp, *sctp_prev; 55 zoneid_t myzoneid; 56 netstackid_t stackid = (netstackid_t)(uintptr_t)kp->ks_private; 57 netstack_t *ns; 58 sctp_stack_t *sctps; 59 60 if (kp == NULL|| kp->ks_data == NULL) 61 return (EIO); 62 63 if (rw == KSTAT_WRITE) 64 return (EACCES); 65 66 ns = netstack_find_by_stackid(stackid); 67 if (ns == NULL) 68 return (-1); 69 sctps = ns->netstack_sctp; 70 if (sctps == NULL) { 71 netstack_rele(ns); 72 return (-1); 73 } 74 myzoneid = netstackid_to_zoneid(stackid); 75 76 /* 77 * Get the number of current associations and gather their 78 * individual set of statistics. 79 */ 80 SET_MIB(sctps->sctps_mib.sctpCurrEstab, 0); 81 sctp_prev = NULL; 82 mutex_enter(&sctps->sctps_g_lock); 83 sctp = list_head(&sctps->sctps_g_list); 84 while (sctp != NULL) { 85 mutex_enter(&sctp->sctp_reflock); 86 if (sctp->sctp_condemned) { 87 mutex_exit(&sctp->sctp_reflock); 88 sctp = list_next(&sctps->sctps_g_list, sctp); 89 continue; 90 } 91 sctp->sctp_refcnt++; 92 mutex_exit(&sctp->sctp_reflock); 93 mutex_exit(&sctps->sctps_g_lock); 94 if (sctp_prev != NULL) 95 SCTP_REFRELE(sctp_prev); 96 if (sctp->sctp_connp->conn_zoneid != myzoneid) 97 goto next_sctp; 98 if (sctp->sctp_state == SCTPS_ESTABLISHED || 99 sctp->sctp_state == SCTPS_SHUTDOWN_PENDING || 100 sctp->sctp_state == SCTPS_SHUTDOWN_RECEIVED) { 101 BUMP_MIB(&sctps->sctps_mib, sctpCurrEstab); 102 } 103 104 if (sctp->sctp_opkts) { 105 UPDATE_MIB(&sctps->sctps_mib, sctpOutSCTPPkts, 106 sctp->sctp_opkts); 107 sctp->sctp_opkts = 0; 108 } 109 110 if (sctp->sctp_obchunks) { 111 UPDATE_MIB(&sctps->sctps_mib, sctpOutCtrlChunks, 112 sctp->sctp_obchunks); 113 UPDATE_LOCAL(sctp->sctp_cum_obchunks, 114 sctp->sctp_obchunks); 115 sctp->sctp_obchunks = 0; 116 } 117 118 if (sctp->sctp_odchunks) { 119 UPDATE_MIB(&sctps->sctps_mib, sctpOutOrderChunks, 120 sctp->sctp_odchunks); 121 UPDATE_LOCAL(sctp->sctp_cum_odchunks, 122 sctp->sctp_odchunks); 123 sctp->sctp_odchunks = 0; 124 } 125 126 if (sctp->sctp_oudchunks) { 127 UPDATE_MIB(&sctps->sctps_mib, sctpOutUnorderChunks, 128 sctp->sctp_oudchunks); 129 UPDATE_LOCAL(sctp->sctp_cum_oudchunks, 130 sctp->sctp_oudchunks); 131 sctp->sctp_oudchunks = 0; 132 } 133 134 if (sctp->sctp_rxtchunks) { 135 UPDATE_MIB(&sctps->sctps_mib, sctpRetransChunks, 136 sctp->sctp_rxtchunks); 137 UPDATE_LOCAL(sctp->sctp_cum_rxtchunks, 138 sctp->sctp_rxtchunks); 139 sctp->sctp_rxtchunks = 0; 140 } 141 142 if (sctp->sctp_ipkts) { 143 UPDATE_MIB(&sctps->sctps_mib, sctpInSCTPPkts, 144 sctp->sctp_ipkts); 145 sctp->sctp_ipkts = 0; 146 } 147 148 if (sctp->sctp_ibchunks) { 149 UPDATE_MIB(&sctps->sctps_mib, sctpInCtrlChunks, 150 sctp->sctp_ibchunks); 151 UPDATE_LOCAL(sctp->sctp_cum_ibchunks, 152 sctp->sctp_ibchunks); 153 sctp->sctp_ibchunks = 0; 154 } 155 156 if (sctp->sctp_idchunks) { 157 UPDATE_MIB(&sctps->sctps_mib, sctpInOrderChunks, 158 sctp->sctp_idchunks); 159 UPDATE_LOCAL(sctp->sctp_cum_idchunks, 160 sctp->sctp_idchunks); 161 sctp->sctp_idchunks = 0; 162 } 163 164 if (sctp->sctp_iudchunks) { 165 UPDATE_MIB(&sctps->sctps_mib, sctpInUnorderChunks, 166 sctp->sctp_iudchunks); 167 UPDATE_LOCAL(sctp->sctp_cum_iudchunks, 168 sctp->sctp_iudchunks); 169 sctp->sctp_iudchunks = 0; 170 } 171 172 if (sctp->sctp_fragdmsgs) { 173 UPDATE_MIB(&sctps->sctps_mib, sctpFragUsrMsgs, 174 sctp->sctp_fragdmsgs); 175 sctp->sctp_fragdmsgs = 0; 176 } 177 178 if (sctp->sctp_reassmsgs) { 179 UPDATE_MIB(&sctps->sctps_mib, sctpReasmUsrMsgs, 180 sctp->sctp_reassmsgs); 181 sctp->sctp_reassmsgs = 0; 182 } 183 184 next_sctp: 185 sctp_prev = sctp; 186 mutex_enter(&sctps->sctps_g_lock); 187 sctp = list_next(&sctps->sctps_g_list, sctp); 188 } 189 mutex_exit(&sctps->sctps_g_lock); 190 if (sctp_prev != NULL) 191 SCTP_REFRELE(sctp_prev); 192 193 /* Copy data from the SCTP MIB */ 194 sctpkp = (sctp_named_kstat_t *)kp->ks_data; 195 196 /* These are from global ndd params. */ 197 sctpkp->sctpRtoMin.value.ui32 = sctps->sctps_rto_ming; 198 sctpkp->sctpRtoMax.value.ui32 = sctps->sctps_rto_maxg; 199 sctpkp->sctpRtoInitial.value.ui32 = sctps->sctps_rto_initialg; 200 sctpkp->sctpValCookieLife.value.ui32 = sctps->sctps_cookie_life; 201 sctpkp->sctpMaxInitRetr.value.ui32 = sctps->sctps_max_init_retr; 202 203 sctpkp->sctpCurrEstab.value.i32 = sctps->sctps_mib.sctpCurrEstab; 204 sctpkp->sctpActiveEstab.value.i32 = sctps->sctps_mib.sctpActiveEstab; 205 sctpkp->sctpPassiveEstab.value.i32 = sctps->sctps_mib.sctpPassiveEstab; 206 sctpkp->sctpAborted.value.i32 = sctps->sctps_mib.sctpAborted; 207 sctpkp->sctpShutdowns.value.i32 = sctps->sctps_mib.sctpShutdowns; 208 sctpkp->sctpOutOfBlue.value.i32 = sctps->sctps_mib.sctpOutOfBlue; 209 sctpkp->sctpChecksumError.value.i32 = 210 sctps->sctps_mib.sctpChecksumError; 211 sctpkp->sctpOutCtrlChunks.value.i64 = 212 sctps->sctps_mib.sctpOutCtrlChunks; 213 sctpkp->sctpOutOrderChunks.value.i64 = 214 sctps->sctps_mib.sctpOutOrderChunks; 215 sctpkp->sctpOutUnorderChunks.value.i64 = 216 sctps->sctps_mib.sctpOutUnorderChunks; 217 sctpkp->sctpRetransChunks.value.i64 = 218 sctps->sctps_mib.sctpRetransChunks; 219 sctpkp->sctpOutAck.value.i32 = sctps->sctps_mib.sctpOutAck; 220 sctpkp->sctpOutAckDelayed.value.i32 = 221 sctps->sctps_mib.sctpOutAckDelayed; 222 sctpkp->sctpOutWinUpdate.value.i32 = sctps->sctps_mib.sctpOutWinUpdate; 223 sctpkp->sctpOutFastRetrans.value.i32 = 224 sctps->sctps_mib.sctpOutFastRetrans; 225 sctpkp->sctpOutWinProbe.value.i32 = sctps->sctps_mib.sctpOutWinProbe; 226 sctpkp->sctpInCtrlChunks.value.i64 = sctps->sctps_mib.sctpInCtrlChunks; 227 sctpkp->sctpInOrderChunks.value.i64 = 228 sctps->sctps_mib.sctpInOrderChunks; 229 sctpkp->sctpInUnorderChunks.value.i64 = 230 sctps->sctps_mib.sctpInUnorderChunks; 231 sctpkp->sctpInAck.value.i32 = sctps->sctps_mib.sctpInAck; 232 sctpkp->sctpInDupAck.value.i32 = sctps->sctps_mib.sctpInDupAck; 233 sctpkp->sctpInAckUnsent.value.i32 = sctps->sctps_mib.sctpInAckUnsent; 234 sctpkp->sctpFragUsrMsgs.value.i64 = sctps->sctps_mib.sctpFragUsrMsgs; 235 sctpkp->sctpReasmUsrMsgs.value.i64 = sctps->sctps_mib.sctpReasmUsrMsgs; 236 sctpkp->sctpOutSCTPPkts.value.i64 = sctps->sctps_mib.sctpOutSCTPPkts; 237 sctpkp->sctpInSCTPPkts.value.i64 = sctps->sctps_mib.sctpInSCTPPkts; 238 sctpkp->sctpInInvalidCookie.value.i32 = 239 sctps->sctps_mib.sctpInInvalidCookie; 240 sctpkp->sctpTimRetrans.value.i32 = sctps->sctps_mib.sctpTimRetrans; 241 sctpkp->sctpTimRetransDrop.value.i32 = 242 sctps->sctps_mib.sctpTimRetransDrop; 243 sctpkp->sctpTimHeartBeatProbe.value.i32 = 244 sctps->sctps_mib.sctpTimHeartBeatProbe; 245 sctpkp->sctpTimHeartBeatDrop.value.i32 = 246 sctps->sctps_mib.sctpTimHeartBeatDrop; 247 sctpkp->sctpListenDrop.value.i32 = sctps->sctps_mib.sctpListenDrop; 248 sctpkp->sctpInClosed.value.i32 = sctps->sctps_mib.sctpInClosed; 249 250 netstack_rele(ns); 251 return (0); 252 } 253 254 void * 255 sctp_kstat_init(netstackid_t stackid) 256 { 257 kstat_t *ksp; 258 259 sctp_named_kstat_t template = { 260 { "sctpRtoAlgorithm", KSTAT_DATA_INT32, 0 }, 261 { "sctpRtoMin", KSTAT_DATA_UINT32, 0 }, 262 { "sctpRtoMax", KSTAT_DATA_UINT32, 0 }, 263 { "sctpRtoInitial", KSTAT_DATA_UINT32, 0 }, 264 { "sctpMaxAssocs", KSTAT_DATA_INT32, 0 }, 265 { "sctpValCookieLife", KSTAT_DATA_UINT32, 0 }, 266 { "sctpMaxInitRetr", KSTAT_DATA_UINT32, 0 }, 267 { "sctpCurrEstab", KSTAT_DATA_INT32, 0 }, 268 { "sctpActiveEstab", KSTAT_DATA_INT32, 0 }, 269 { "sctpPassiveEstab", KSTAT_DATA_INT32, 0 }, 270 { "sctpAborted", KSTAT_DATA_INT32, 0 }, 271 { "sctpShutdowns", KSTAT_DATA_INT32, 0 }, 272 { "sctpOutOfBlue", KSTAT_DATA_INT32, 0 }, 273 { "sctpChecksumError", KSTAT_DATA_INT32, 0 }, 274 { "sctpOutCtrlChunks", KSTAT_DATA_INT64, 0 }, 275 { "sctpOutOrderChunks", KSTAT_DATA_INT64, 0 }, 276 { "sctpOutUnorderChunks", KSTAT_DATA_INT64, 0 }, 277 { "sctpRetransChunks", KSTAT_DATA_INT64, 0 }, 278 { "sctpOutAck", KSTAT_DATA_INT32, 0 }, 279 { "sctpOutAckDelayed", KSTAT_DATA_INT32, 0 }, 280 { "sctpOutWinUpdate", KSTAT_DATA_INT32, 0 }, 281 { "sctpOutFastRetrans", KSTAT_DATA_INT32, 0 }, 282 { "sctpOutWinProbe", KSTAT_DATA_INT32, 0 }, 283 { "sctpInCtrlChunks", KSTAT_DATA_INT64, 0 }, 284 { "sctpInOrderChunks", KSTAT_DATA_INT64, 0 }, 285 { "sctpInUnorderChunks", KSTAT_DATA_INT64, 0 }, 286 { "sctpInAck", KSTAT_DATA_INT32, 0 }, 287 { "sctpInDupAck", KSTAT_DATA_INT32, 0 }, 288 { "sctpInAckUnsent", KSTAT_DATA_INT32, 0 }, 289 { "sctpFragUsrMsgs", KSTAT_DATA_INT64, 0 }, 290 { "sctpReasmUsrMsgs", KSTAT_DATA_INT64, 0 }, 291 { "sctpOutSCTPPkts", KSTAT_DATA_INT64, 0 }, 292 { "sctpInSCTPPkts", KSTAT_DATA_INT64, 0 }, 293 { "sctpInInvalidCookie", KSTAT_DATA_INT32, 0 }, 294 { "sctpTimRetrans", KSTAT_DATA_INT32, 0 }, 295 { "sctpTimRetransDrop", KSTAT_DATA_INT32, 0 }, 296 { "sctpTimHearBeatProbe", KSTAT_DATA_INT32, 0 }, 297 { "sctpTimHearBeatDrop", KSTAT_DATA_INT32, 0 }, 298 { "sctpListenDrop", KSTAT_DATA_INT32, 0 }, 299 { "sctpInClosed", KSTAT_DATA_INT32, 0 } 300 }; 301 302 ksp = kstat_create_netstack(SCTP_MOD_NAME, 0, "sctp", "mib2", 303 KSTAT_TYPE_NAMED, NUM_OF_FIELDS(sctp_named_kstat_t), 0, stackid); 304 305 if (ksp == NULL || ksp->ks_data == NULL) 306 return (NULL); 307 308 /* These won't change. */ 309 template.sctpRtoAlgorithm.value.i32 = MIB2_SCTP_RTOALGO_VANJ; 310 template.sctpMaxAssocs.value.i32 = -1; 311 312 bcopy(&template, ksp->ks_data, sizeof (template)); 313 ksp->ks_update = sctp_kstat_update; 314 ksp->ks_private = (void *)(uintptr_t)stackid; 315 316 kstat_install(ksp); 317 return (ksp); 318 } 319 320 /* 321 * The following kstats are for debugging purposes. They keep 322 * track of problems which should not happen normally. But in 323 * those cases which they do happen, these kstats would be handy 324 * for engineers to diagnose the problems. They are not intended 325 * to be consumed by customers. 326 */ 327 void * 328 sctp_kstat2_init(netstackid_t stackid, sctp_kstat_t *sctps_statisticsp) 329 { 330 kstat_t *ksp; 331 332 sctp_kstat_t template = { 333 { "sctp_add_faddr", KSTAT_DATA_UINT64 }, 334 { "sctp_add_timer", KSTAT_DATA_UINT64 }, 335 { "sctp_conn_create", KSTAT_DATA_UINT64 }, 336 { "sctp_find_next_tq", KSTAT_DATA_UINT64 }, 337 { "sctp_fr_add_hdr", KSTAT_DATA_UINT64 }, 338 { "sctp_fr_not_found", KSTAT_DATA_UINT64 }, 339 { "sctp_output_failed", KSTAT_DATA_UINT64 }, 340 { "sctp_rexmit_failed", KSTAT_DATA_UINT64 }, 341 { "sctp_send_init_failed", KSTAT_DATA_UINT64 }, 342 { "sctp_send_cookie_failed", KSTAT_DATA_UINT64 }, 343 { "sctp_send_cookie_ack_failed", KSTAT_DATA_UINT64 }, 344 { "sctp_send_err_failed", KSTAT_DATA_UINT64 }, 345 { "sctp_send_sack_failed", KSTAT_DATA_UINT64 }, 346 { "sctp_send_shutdown_failed", KSTAT_DATA_UINT64 }, 347 { "sctp_send_shutdown_ack_failed", KSTAT_DATA_UINT64 }, 348 { "sctp_send_shutdown_comp_failed", KSTAT_DATA_UINT64 }, 349 { "sctp_send_user_abort_failed", KSTAT_DATA_UINT64 }, 350 { "sctp_send_asconf_failed", KSTAT_DATA_UINT64 }, 351 { "sctp_send_asconf_ack_failed", KSTAT_DATA_UINT64 }, 352 { "sctp_send_ftsn_failed", KSTAT_DATA_UINT64 }, 353 { "sctp_send_hb_failed", KSTAT_DATA_UINT64 }, 354 { "sctp_return_hb_failed", KSTAT_DATA_UINT64 }, 355 { "sctp_ss_rexmit_failed", KSTAT_DATA_UINT64 }, 356 { "sctp_cl_connect", KSTAT_DATA_UINT64 }, 357 { "sctp_cl_assoc_change", KSTAT_DATA_UINT64 }, 358 { "sctp_cl_check_addrs", KSTAT_DATA_UINT64 }, 359 }; 360 361 ksp = kstat_create_netstack(SCTP_MOD_NAME, 0, "sctpstat", "net", 362 KSTAT_TYPE_NAMED, NUM_OF_FIELDS(template), KSTAT_FLAG_VIRTUAL, 363 stackid); 364 365 if (ksp == NULL) 366 return (NULL); 367 368 bcopy(&template, sctps_statisticsp, sizeof (template)); 369 ksp->ks_data = (void *)sctps_statisticsp; 370 ksp->ks_private = (void *)(uintptr_t)stackid; 371 372 kstat_install(ksp); 373 return (ksp); 374 } 375 376 void 377 sctp_kstat_fini(netstackid_t stackid, kstat_t *ksp) 378 { 379 if (ksp != NULL) { 380 ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 381 kstat_delete_netstack(ksp, stackid); 382 } 383 } 384 385 void 386 sctp_kstat2_fini(netstackid_t stackid, kstat_t *ksp) 387 { 388 if (ksp != NULL) { 389 ASSERT(stackid == (netstackid_t)(uintptr_t)ksp->ks_private); 390 kstat_delete_netstack(ksp, stackid); 391 } 392 } 393 394 /* 395 * Return SNMP global stats in buffer in mpdata. 396 * Return associatiation table in mp_conn_data, 397 * local address table in mp_local_data, and 398 * remote address table in mp_rem_data. 399 */ 400 mblk_t * 401 sctp_snmp_get_mib2(queue_t *q, mblk_t *mpctl, sctp_stack_t *sctps) 402 { 403 mblk_t *mpdata, *mp_ret; 404 mblk_t *mp_conn_ctl = NULL; 405 mblk_t *mp_conn_data; 406 mblk_t *mp_conn_tail = NULL; 407 mblk_t *mp_local_ctl = NULL; 408 mblk_t *mp_local_data; 409 mblk_t *mp_local_tail = NULL; 410 mblk_t *mp_rem_ctl = NULL; 411 mblk_t *mp_rem_data; 412 mblk_t *mp_rem_tail = NULL; 413 mblk_t *mp_attr_ctl = NULL; 414 mblk_t *mp_attr_data; 415 mblk_t *mp_attr_tail = NULL; 416 struct opthdr *optp; 417 sctp_t *sctp, *sctp_prev = NULL; 418 sctp_faddr_t *fp; 419 mib2_sctpConnEntry_t sce; 420 mib2_sctpConnLocalEntry_t scle; 421 mib2_sctpConnRemoteEntry_t scre; 422 mib2_transportMLPEntry_t mlp; 423 int i; 424 int l; 425 int scanned = 0; 426 zoneid_t zoneid = Q_TO_CONN(q)->conn_zoneid; 427 conn_t *connp; 428 boolean_t needattr; 429 int idx; 430 431 /* 432 * Make copies of the original message. 433 * mpctl will hold SCTP counters, 434 * mp_conn_ctl will hold list of connections. 435 */ 436 mp_ret = copymsg(mpctl); 437 mp_conn_ctl = copymsg(mpctl); 438 mp_local_ctl = copymsg(mpctl); 439 mp_rem_ctl = copymsg(mpctl); 440 mp_attr_ctl = copymsg(mpctl); 441 442 mpdata = mpctl->b_cont; 443 444 if (mp_conn_ctl == NULL || mp_local_ctl == NULL || 445 mp_rem_ctl == NULL || mp_attr_ctl == NULL || mpdata == NULL) { 446 freemsg(mp_attr_ctl); 447 freemsg(mp_rem_ctl); 448 freemsg(mp_local_ctl); 449 freemsg(mp_conn_ctl); 450 freemsg(mp_ret); 451 freemsg(mpctl); 452 return (NULL); 453 } 454 mp_conn_data = mp_conn_ctl->b_cont; 455 mp_local_data = mp_local_ctl->b_cont; 456 mp_rem_data = mp_rem_ctl->b_cont; 457 mp_attr_data = mp_attr_ctl->b_cont; 458 459 /* hostname address parameters are not supported in Solaris */ 460 sce.sctpAssocRemHostName.o_length = 0; 461 sce.sctpAssocRemHostName.o_bytes[0] = 0; 462 463 /* build table of connections -- need count in fixed part */ 464 SET_MIB(sctps->sctps_mib.sctpRtoAlgorithm, MIB2_SCTP_RTOALGO_VANJ); 465 SET_MIB(sctps->sctps_mib.sctpRtoMin, sctps->sctps_rto_ming); 466 SET_MIB(sctps->sctps_mib.sctpRtoMax, sctps->sctps_rto_maxg); 467 SET_MIB(sctps->sctps_mib.sctpRtoInitial, sctps->sctps_rto_initialg); 468 SET_MIB(sctps->sctps_mib.sctpMaxAssocs, -1); 469 SET_MIB(sctps->sctps_mib.sctpValCookieLife, sctps->sctps_cookie_life); 470 SET_MIB(sctps->sctps_mib.sctpMaxInitRetr, sctps->sctps_max_init_retr); 471 SET_MIB(sctps->sctps_mib.sctpCurrEstab, 0); 472 473 idx = 0; 474 mutex_enter(&sctps->sctps_g_lock); 475 sctp = list_head(&sctps->sctps_g_list); 476 while (sctp != NULL) { 477 mutex_enter(&sctp->sctp_reflock); 478 if (sctp->sctp_condemned) { 479 mutex_exit(&sctp->sctp_reflock); 480 sctp = list_next(&sctps->sctps_g_list, sctp); 481 continue; 482 } 483 sctp->sctp_refcnt++; 484 mutex_exit(&sctp->sctp_reflock); 485 mutex_exit(&sctps->sctps_g_lock); 486 if (sctp_prev != NULL) 487 SCTP_REFRELE(sctp_prev); 488 if (sctp->sctp_connp->conn_zoneid != zoneid) 489 goto next_sctp; 490 if (sctp->sctp_state == SCTPS_ESTABLISHED || 491 sctp->sctp_state == SCTPS_SHUTDOWN_PENDING || 492 sctp->sctp_state == SCTPS_SHUTDOWN_RECEIVED) { 493 BUMP_MIB(&sctps->sctps_mib, sctpCurrEstab); 494 } 495 UPDATE_MIB(&sctps->sctps_mib, 496 sctpOutSCTPPkts, sctp->sctp_opkts); 497 sctp->sctp_opkts = 0; 498 UPDATE_MIB(&sctps->sctps_mib, 499 sctpOutCtrlChunks, sctp->sctp_obchunks); 500 UPDATE_LOCAL(sctp->sctp_cum_obchunks, 501 sctp->sctp_obchunks); 502 sctp->sctp_obchunks = 0; 503 UPDATE_MIB(&sctps->sctps_mib, 504 sctpOutOrderChunks, sctp->sctp_odchunks); 505 UPDATE_LOCAL(sctp->sctp_cum_odchunks, 506 sctp->sctp_odchunks); 507 sctp->sctp_odchunks = 0; 508 UPDATE_MIB(&sctps->sctps_mib, sctpOutUnorderChunks, 509 sctp->sctp_oudchunks); 510 UPDATE_LOCAL(sctp->sctp_cum_oudchunks, 511 sctp->sctp_oudchunks); 512 sctp->sctp_oudchunks = 0; 513 UPDATE_MIB(&sctps->sctps_mib, 514 sctpRetransChunks, sctp->sctp_rxtchunks); 515 UPDATE_LOCAL(sctp->sctp_cum_rxtchunks, 516 sctp->sctp_rxtchunks); 517 sctp->sctp_rxtchunks = 0; 518 UPDATE_MIB(&sctps->sctps_mib, 519 sctpInSCTPPkts, sctp->sctp_ipkts); 520 sctp->sctp_ipkts = 0; 521 UPDATE_MIB(&sctps->sctps_mib, 522 sctpInCtrlChunks, sctp->sctp_ibchunks); 523 UPDATE_LOCAL(sctp->sctp_cum_ibchunks, 524 sctp->sctp_ibchunks); 525 sctp->sctp_ibchunks = 0; 526 UPDATE_MIB(&sctps->sctps_mib, 527 sctpInOrderChunks, sctp->sctp_idchunks); 528 UPDATE_LOCAL(sctp->sctp_cum_idchunks, 529 sctp->sctp_idchunks); 530 sctp->sctp_idchunks = 0; 531 UPDATE_MIB(&sctps->sctps_mib, sctpInUnorderChunks, 532 sctp->sctp_iudchunks); 533 UPDATE_LOCAL(sctp->sctp_cum_iudchunks, 534 sctp->sctp_iudchunks); 535 sctp->sctp_iudchunks = 0; 536 UPDATE_MIB(&sctps->sctps_mib, 537 sctpFragUsrMsgs, sctp->sctp_fragdmsgs); 538 sctp->sctp_fragdmsgs = 0; 539 UPDATE_MIB(&sctps->sctps_mib, 540 sctpReasmUsrMsgs, sctp->sctp_reassmsgs); 541 sctp->sctp_reassmsgs = 0; 542 543 sce.sctpAssocId = ntohl(sctp->sctp_lvtag); 544 sce.sctpAssocLocalPort = ntohs(sctp->sctp_connp->conn_lport); 545 sce.sctpAssocRemPort = ntohs(sctp->sctp_connp->conn_fport); 546 547 RUN_SCTP(sctp); 548 if (sctp->sctp_primary != NULL) { 549 fp = sctp->sctp_primary; 550 551 if (IN6_IS_ADDR_V4MAPPED(&fp->faddr)) { 552 sce.sctpAssocRemPrimAddrType = 553 MIB2_SCTP_ADDR_V4; 554 } else { 555 sce.sctpAssocRemPrimAddrType = 556 MIB2_SCTP_ADDR_V6; 557 } 558 sce.sctpAssocRemPrimAddr = fp->faddr; 559 sce.sctpAssocLocPrimAddr = fp->saddr; 560 sce.sctpAssocHeartBeatInterval = TICK_TO_MSEC( 561 fp->hb_interval); 562 } else { 563 sce.sctpAssocRemPrimAddrType = MIB2_SCTP_ADDR_V4; 564 bzero(&sce.sctpAssocRemPrimAddr, 565 sizeof (sce.sctpAssocRemPrimAddr)); 566 bzero(&sce.sctpAssocLocPrimAddr, 567 sizeof (sce.sctpAssocLocPrimAddr)); 568 sce.sctpAssocHeartBeatInterval = 569 sctps->sctps_heartbeat_interval; 570 } 571 572 /* 573 * Table for local addresses 574 */ 575 scanned = 0; 576 for (i = 0; i < SCTP_IPIF_HASH; i++) { 577 sctp_saddr_ipif_t *obj; 578 579 if (sctp->sctp_saddrs[i].ipif_count == 0) 580 continue; 581 obj = list_head(&sctp->sctp_saddrs[i].sctp_ipif_list); 582 for (l = 0; l < sctp->sctp_saddrs[i].ipif_count; l++) { 583 sctp_ipif_t *sctp_ipif; 584 in6_addr_t addr; 585 586 sctp_ipif = obj->saddr_ipifp; 587 addr = sctp_ipif->sctp_ipif_saddr; 588 scanned++; 589 scle.sctpAssocId = ntohl(sctp->sctp_lvtag); 590 if (IN6_IS_ADDR_V4MAPPED(&addr)) { 591 scle.sctpAssocLocalAddrType = 592 MIB2_SCTP_ADDR_V4; 593 } else { 594 scle.sctpAssocLocalAddrType = 595 MIB2_SCTP_ADDR_V6; 596 } 597 scle.sctpAssocLocalAddr = addr; 598 (void) snmp_append_data2(mp_local_data, 599 &mp_local_tail, (char *)&scle, 600 sizeof (scle)); 601 if (scanned >= sctp->sctp_nsaddrs) 602 goto done; 603 obj = list_next(&sctp-> 604 sctp_saddrs[i].sctp_ipif_list, obj); 605 } 606 } 607 done: 608 /* 609 * Table for remote addresses 610 */ 611 for (fp = sctp->sctp_faddrs; fp; fp = fp->next) { 612 scre.sctpAssocId = ntohl(sctp->sctp_lvtag); 613 if (IN6_IS_ADDR_V4MAPPED(&fp->faddr)) { 614 scre.sctpAssocRemAddrType = MIB2_SCTP_ADDR_V4; 615 } else { 616 scre.sctpAssocRemAddrType = MIB2_SCTP_ADDR_V6; 617 } 618 scre.sctpAssocRemAddr = fp->faddr; 619 if (fp->state == SCTP_FADDRS_ALIVE) { 620 scre.sctpAssocRemAddrActive = 621 scre.sctpAssocRemAddrHBActive = 622 MIB2_SCTP_ACTIVE; 623 } else { 624 scre.sctpAssocRemAddrActive = 625 scre.sctpAssocRemAddrHBActive = 626 MIB2_SCTP_INACTIVE; 627 } 628 scre.sctpAssocRemAddrRTO = TICK_TO_MSEC(fp->rto); 629 scre.sctpAssocRemAddrMaxPathRtx = fp->max_retr; 630 scre.sctpAssocRemAddrRtx = fp->T3expire; 631 (void) snmp_append_data2(mp_rem_data, &mp_rem_tail, 632 (char *)&scre, sizeof (scre)); 633 } 634 connp = sctp->sctp_connp; 635 needattr = B_FALSE; 636 bzero(&mlp, sizeof (mlp)); 637 if (connp->conn_mlp_type != mlptSingle) { 638 if (connp->conn_mlp_type == mlptShared || 639 connp->conn_mlp_type == mlptBoth) 640 mlp.tme_flags |= MIB2_TMEF_SHARED; 641 if (connp->conn_mlp_type == mlptPrivate || 642 connp->conn_mlp_type == mlptBoth) 643 mlp.tme_flags |= MIB2_TMEF_PRIVATE; 644 needattr = B_TRUE; 645 } 646 if (connp->conn_anon_mlp) { 647 mlp.tme_flags |= MIB2_TMEF_ANONMLP; 648 needattr = B_TRUE; 649 } 650 switch (connp->conn_mac_mode) { 651 case CONN_MAC_DEFAULT: 652 break; 653 case CONN_MAC_AWARE: 654 mlp.tme_flags |= MIB2_TMEF_MACEXEMPT; 655 needattr = B_TRUE; 656 break; 657 case CONN_MAC_IMPLICIT: 658 mlp.tme_flags |= MIB2_TMEF_MACIMPLICIT; 659 needattr = B_TRUE; 660 break; 661 } 662 if (sctp->sctp_connp->conn_ixa->ixa_tsl != NULL) { 663 ts_label_t *tsl; 664 665 tsl = sctp->sctp_connp->conn_ixa->ixa_tsl; 666 mlp.tme_flags |= MIB2_TMEF_IS_LABELED; 667 mlp.tme_doi = label2doi(tsl); 668 mlp.tme_label = *label2bslabel(tsl); 669 needattr = B_TRUE; 670 } 671 WAKE_SCTP(sctp); 672 sce.sctpAssocState = sctp_snmp_state(sctp); 673 sce.sctpAssocInStreams = sctp->sctp_num_istr; 674 sce.sctpAssocOutStreams = sctp->sctp_num_ostr; 675 sce.sctpAssocMaxRetr = sctp->sctp_pa_max_rxt; 676 /* A 0 here indicates that no primary process is known */ 677 sce.sctpAssocPrimProcess = 0; 678 sce.sctpAssocT1expired = sctp->sctp_T1expire; 679 sce.sctpAssocT2expired = sctp->sctp_T2expire; 680 sce.sctpAssocRtxChunks = sctp->sctp_T3expire; 681 sce.sctpAssocStartTime = sctp->sctp_assoc_start_time; 682 sce.sctpConnEntryInfo.ce_sendq = sctp->sctp_unacked + 683 sctp->sctp_unsent; 684 sce.sctpConnEntryInfo.ce_recvq = sctp->sctp_rxqueued; 685 sce.sctpConnEntryInfo.ce_swnd = sctp->sctp_frwnd; 686 sce.sctpConnEntryInfo.ce_rwnd = sctp->sctp_rwnd; 687 sce.sctpConnEntryInfo.ce_mss = sctp->sctp_mss; 688 (void) snmp_append_data2(mp_conn_data, &mp_conn_tail, 689 (char *)&sce, sizeof (sce)); 690 mlp.tme_connidx = idx++; 691 if (needattr) 692 (void) snmp_append_data2(mp_attr_ctl->b_cont, 693 &mp_attr_tail, (char *)&mlp, sizeof (mlp)); 694 next_sctp: 695 sctp_prev = sctp; 696 mutex_enter(&sctps->sctps_g_lock); 697 sctp = list_next(&sctps->sctps_g_list, sctp); 698 } 699 mutex_exit(&sctps->sctps_g_lock); 700 if (sctp_prev != NULL) 701 SCTP_REFRELE(sctp_prev); 702 703 /* fixed length structure for IPv4 and IPv6 counters */ 704 SET_MIB(sctps->sctps_mib.sctpEntrySize, sizeof (sce)); 705 SET_MIB(sctps->sctps_mib.sctpLocalEntrySize, sizeof (scle)); 706 SET_MIB(sctps->sctps_mib.sctpRemoteEntrySize, sizeof (scre)); 707 optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)]; 708 optp->level = MIB2_SCTP; 709 optp->name = 0; 710 (void) snmp_append_data(mpdata, (char *)&sctps->sctps_mib, 711 sizeof (sctps->sctps_mib)); 712 optp->len = msgdsize(mpdata); 713 qreply(q, mpctl); 714 715 /* table of connections... */ 716 optp = (struct opthdr *)&mp_conn_ctl->b_rptr[ 717 sizeof (struct T_optmgmt_ack)]; 718 optp->level = MIB2_SCTP; 719 optp->name = MIB2_SCTP_CONN; 720 optp->len = msgdsize(mp_conn_data); 721 qreply(q, mp_conn_ctl); 722 723 /* assoc local address table */ 724 optp = (struct opthdr *)&mp_local_ctl->b_rptr[ 725 sizeof (struct T_optmgmt_ack)]; 726 optp->level = MIB2_SCTP; 727 optp->name = MIB2_SCTP_CONN_LOCAL; 728 optp->len = msgdsize(mp_local_data); 729 qreply(q, mp_local_ctl); 730 731 /* assoc remote address table */ 732 optp = (struct opthdr *)&mp_rem_ctl->b_rptr[ 733 sizeof (struct T_optmgmt_ack)]; 734 optp->level = MIB2_SCTP; 735 optp->name = MIB2_SCTP_CONN_REMOTE; 736 optp->len = msgdsize(mp_rem_data); 737 qreply(q, mp_rem_ctl); 738 739 /* table of MLP attributes */ 740 optp = (struct opthdr *)&mp_attr_ctl->b_rptr[ 741 sizeof (struct T_optmgmt_ack)]; 742 optp->level = MIB2_SCTP; 743 optp->name = EXPER_XPORT_MLP; 744 optp->len = msgdsize(mp_attr_data); 745 if (optp->len == 0) 746 freemsg(mp_attr_ctl); 747 else 748 qreply(q, mp_attr_ctl); 749 750 return (mp_ret); 751 } 752 753 /* Translate SCTP state to MIB2 SCTP state. */ 754 static int 755 sctp_snmp_state(sctp_t *sctp) 756 { 757 if (sctp == NULL) 758 return (0); 759 760 switch (sctp->sctp_state) { 761 case SCTPS_IDLE: 762 case SCTPS_BOUND: 763 return (MIB2_SCTP_closed); 764 case SCTPS_LISTEN: 765 return (MIB2_SCTP_listen); 766 case SCTPS_COOKIE_WAIT: 767 return (MIB2_SCTP_cookieWait); 768 case SCTPS_COOKIE_ECHOED: 769 return (MIB2_SCTP_cookieEchoed); 770 case SCTPS_ESTABLISHED: 771 return (MIB2_SCTP_established); 772 case SCTPS_SHUTDOWN_PENDING: 773 return (MIB2_SCTP_shutdownPending); 774 case SCTPS_SHUTDOWN_SENT: 775 return (MIB2_SCTP_shutdownSent); 776 case SCTPS_SHUTDOWN_RECEIVED: 777 return (MIB2_SCTP_shutdownReceived); 778 case SCTPS_SHUTDOWN_ACK_SENT: 779 return (MIB2_SCTP_shutdownAckSent); 780 default: 781 return (0); 782 } 783 } 784