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