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