1 /** 2 * @file 3 * Management Information Base II (RFC1213) TCP objects and functions. 4 */ 5 6 /* 7 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without modification, 11 * are permitted provided that the following conditions are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright notice, 14 * this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright notice, 16 * this list of conditions and the following disclaimer in the documentation 17 * and/or other materials provided with the distribution. 18 * 3. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 24 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 26 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 30 * OF SUCH DAMAGE. 31 * 32 * Author: Dirk Ziegelmeier <dziegel@gmx.de> 33 * Christiaan Simons <christiaan.simons@axon.tv> 34 */ 35 36 #include "lwip/snmp.h" 37 #include "lwip/apps/snmp.h" 38 #include "lwip/apps/snmp_core.h" 39 #include "lwip/apps/snmp_mib2.h" 40 #include "lwip/apps/snmp_table.h" 41 #include "lwip/apps/snmp_scalar.h" 42 #include "lwip/tcp.h" 43 #include "lwip/priv/tcp_priv.h" 44 #include "lwip/stats.h" 45 46 #include <string.h> 47 48 #if LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP 49 50 #if SNMP_USE_NETCONN 51 #define SYNC_NODE_NAME(node_name) node_name ## _synced 52 #define CREATE_LWIP_SYNC_NODE(oid, node_name) \ 53 static const struct snmp_threadsync_node node_name ## _synced = SNMP_CREATE_THREAD_SYNC_NODE(oid, &node_name.node, &snmp_mib2_lwip_locks); 54 #else 55 #define SYNC_NODE_NAME(node_name) node_name 56 #define CREATE_LWIP_SYNC_NODE(oid, node_name) 57 #endif 58 59 /* --- tcp .1.3.6.1.2.1.6 ----------------------------------------------------- */ 60 61 static s16_t 62 tcp_get_value(struct snmp_node_instance* instance, void* value) 63 { 64 u32_t *uint_ptr = (u32_t*)value; 65 s32_t *sint_ptr = (s32_t*)value; 66 67 switch (instance->node->oid) { 68 case 1: /* tcpRtoAlgorithm, vanj(4) */ 69 *sint_ptr = 4; 70 return sizeof(*sint_ptr); 71 case 2: /* tcpRtoMin */ 72 /* @todo not the actual value, a guess, 73 needs to be calculated */ 74 *sint_ptr = 1000; 75 return sizeof(*sint_ptr); 76 case 3: /* tcpRtoMax */ 77 /* @todo not the actual value, a guess, 78 needs to be calculated */ 79 *sint_ptr = 60000; 80 return sizeof(*sint_ptr); 81 case 4: /* tcpMaxConn */ 82 *sint_ptr = MEMP_NUM_TCP_PCB; 83 return sizeof(*sint_ptr); 84 case 5: /* tcpActiveOpens */ 85 *uint_ptr = STATS_GET(mib2.tcpactiveopens); 86 return sizeof(*uint_ptr); 87 case 6: /* tcpPassiveOpens */ 88 *uint_ptr = STATS_GET(mib2.tcppassiveopens); 89 return sizeof(*uint_ptr); 90 case 7: /* tcpAttemptFails */ 91 *uint_ptr = STATS_GET(mib2.tcpattemptfails); 92 return sizeof(*uint_ptr); 93 case 8: /* tcpEstabResets */ 94 *uint_ptr = STATS_GET(mib2.tcpestabresets); 95 return sizeof(*uint_ptr); 96 case 9: /* tcpCurrEstab */ 97 { 98 u16_t tcpcurrestab = 0; 99 struct tcp_pcb *pcb = tcp_active_pcbs; 100 while (pcb != NULL) { 101 if ((pcb->state == ESTABLISHED) || 102 (pcb->state == CLOSE_WAIT)) { 103 tcpcurrestab++; 104 } 105 pcb = pcb->next; 106 } 107 *uint_ptr = tcpcurrestab; 108 } 109 return sizeof(*uint_ptr); 110 case 10: /* tcpInSegs */ 111 *uint_ptr = STATS_GET(mib2.tcpinsegs); 112 return sizeof(*uint_ptr); 113 case 11: /* tcpOutSegs */ 114 *uint_ptr = STATS_GET(mib2.tcpoutsegs); 115 return sizeof(*uint_ptr); 116 case 12: /* tcpRetransSegs */ 117 *uint_ptr = STATS_GET(mib2.tcpretranssegs); 118 return sizeof(*uint_ptr); 119 case 14: /* tcpInErrs */ 120 *uint_ptr = STATS_GET(mib2.tcpinerrs); 121 return sizeof(*uint_ptr); 122 case 15: /* tcpOutRsts */ 123 *uint_ptr = STATS_GET(mib2.tcpoutrsts); 124 return sizeof(*uint_ptr); 125 case 17: /* tcpHCInSegs */ 126 memset(value, 0, 2*sizeof(u32_t)); /* not supported */ 127 return 2*sizeof(u32_t); 128 case 18: /* tcpHCOutSegs */ 129 memset(value, 0, 2*sizeof(u32_t)); /* not supported */ 130 return 2*sizeof(u32_t); 131 default: 132 LWIP_DEBUGF(SNMP_MIB_DEBUG,("tcp_get_value(): unknown id: %"S32_F"\n", instance->node->oid)); 133 break; 134 } 135 136 return 0; 137 } 138 139 /* --- tcpConnTable --- */ 140 141 #if LWIP_IPV4 142 143 /* list of allowed value ranges for incoming OID */ 144 static const struct snmp_oid_range tcp_ConnTable_oid_ranges[] = { 145 { 0, 0xff }, /* IP A */ 146 { 0, 0xff }, /* IP B */ 147 { 0, 0xff }, /* IP C */ 148 { 0, 0xff }, /* IP D */ 149 { 0, 0xffff }, /* Port */ 150 { 0, 0xff }, /* IP A */ 151 { 0, 0xff }, /* IP B */ 152 { 0, 0xff }, /* IP C */ 153 { 0, 0xff }, /* IP D */ 154 { 0, 0xffff } /* Port */ 155 }; 156 157 static snmp_err_t 158 tcp_ConnTable_get_cell_value_core(struct tcp_pcb *pcb, const u32_t* column, union snmp_variant_value* value, u32_t* value_len) 159 { 160 LWIP_UNUSED_ARG(value_len); 161 162 /* value */ 163 switch (*column) { 164 case 1: /* tcpConnState */ 165 value->u32 = pcb->state + 1; 166 break; 167 case 2: /* tcpConnLocalAddress */ 168 value->u32 = ip_2_ip4(&pcb->local_ip)->addr; 169 break; 170 case 3: /* tcpConnLocalPort */ 171 value->u32 = pcb->local_port; 172 break; 173 case 4: /* tcpConnRemAddress */ 174 if (pcb->state == LISTEN) { 175 value->u32 = IP4_ADDR_ANY4->addr; 176 } else { 177 value->u32 = ip_2_ip4(&pcb->remote_ip)->addr; 178 } 179 break; 180 case 5: /* tcpConnRemPort */ 181 if (pcb->state == LISTEN) { 182 value->u32 = 0; 183 } else { 184 value->u32 = pcb->remote_port; 185 } 186 break; 187 default: 188 LWIP_ASSERT("invalid id", 0); 189 return SNMP_ERR_NOSUCHINSTANCE; 190 } 191 192 return SNMP_ERR_NOERROR; 193 } 194 195 static snmp_err_t 196 tcp_ConnTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) 197 { 198 u8_t i; 199 ip4_addr_t local_ip; 200 ip4_addr_t remote_ip; 201 u16_t local_port; 202 u16_t remote_port; 203 struct tcp_pcb *pcb; 204 205 /* check if incoming OID length and if values are in plausible range */ 206 if (!snmp_oid_in_range(row_oid, row_oid_len, tcp_ConnTable_oid_ranges, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges))) { 207 return SNMP_ERR_NOSUCHINSTANCE; 208 } 209 210 /* get IPs and ports from incoming OID */ 211 snmp_oid_to_ip4(&row_oid[0], &local_ip); /* we know it succeeds because of oid_in_range check above */ 212 local_port = (u16_t)row_oid[4]; 213 snmp_oid_to_ip4(&row_oid[5], &remote_ip); /* we know it succeeds because of oid_in_range check above */ 214 remote_port = (u16_t)row_oid[9]; 215 216 /* find tcp_pcb with requested ips and ports */ 217 for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { 218 pcb = *tcp_pcb_lists[i]; 219 220 while (pcb != NULL) { 221 /* do local IP and local port match? */ 222 if (IP_IS_V4_VAL(pcb->local_ip) && 223 ip4_addr_cmp(&local_ip, ip_2_ip4(&pcb->local_ip)) && (local_port == pcb->local_port)) { 224 225 /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ 226 if (pcb->state == LISTEN) { 227 if (ip4_addr_cmp(&remote_ip, IP4_ADDR_ANY4) && (remote_port == 0)) { 228 /* fill in object properties */ 229 return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); 230 } 231 } else { 232 if (IP_IS_V4_VAL(pcb->remote_ip) && 233 ip4_addr_cmp(&remote_ip, ip_2_ip4(&pcb->remote_ip)) && (remote_port == pcb->remote_port)) { 234 /* fill in object properties */ 235 return tcp_ConnTable_get_cell_value_core(pcb, column, value, value_len); 236 } 237 } 238 } 239 240 pcb = pcb->next; 241 } 242 } 243 244 /* not found */ 245 return SNMP_ERR_NOSUCHINSTANCE; 246 } 247 248 static snmp_err_t 249 tcp_ConnTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) 250 { 251 u8_t i; 252 struct tcp_pcb *pcb; 253 struct snmp_next_oid_state state; 254 u32_t result_temp[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; 255 256 /* init struct to search next oid */ 257 snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)); 258 259 /* iterate over all possible OIDs to find the next one */ 260 for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_lists); i++) { 261 pcb = *tcp_pcb_lists[i]; 262 while (pcb != NULL) { 263 u32_t test_oid[LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges)]; 264 265 if (IP_IS_V4_VAL(pcb->local_ip)) { 266 snmp_ip4_to_oid(ip_2_ip4(&pcb->local_ip), &test_oid[0]); 267 test_oid[4] = pcb->local_port; 268 269 /* PCBs in state LISTEN are not connected and have no remote_ip or remote_port */ 270 if (pcb->state == LISTEN) { 271 snmp_ip4_to_oid(IP4_ADDR_ANY4, &test_oid[5]); 272 test_oid[9] = 0; 273 } else { 274 if (IP_IS_V6_VAL(pcb->remote_ip)) { /* should never happen */ 275 continue; 276 } 277 snmp_ip4_to_oid(ip_2_ip4(&pcb->remote_ip), &test_oid[5]); 278 test_oid[9] = pcb->remote_port; 279 } 280 281 /* check generated OID: is it a candidate for the next one? */ 282 snmp_next_oid_check(&state, test_oid, LWIP_ARRAYSIZE(tcp_ConnTable_oid_ranges), pcb); 283 } 284 285 pcb = pcb->next; 286 } 287 } 288 289 /* did we find a next one? */ 290 if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { 291 snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); 292 /* fill in object properties */ 293 return tcp_ConnTable_get_cell_value_core((struct tcp_pcb*)state.reference, column, value, value_len); 294 } 295 296 /* not found */ 297 return SNMP_ERR_NOSUCHINSTANCE; 298 } 299 300 #endif /* LWIP_IPV4 */ 301 302 /* --- tcpConnectionTable --- */ 303 304 static snmp_err_t 305 tcp_ConnectionTable_get_cell_value_core(const u32_t* column, struct tcp_pcb *pcb, union snmp_variant_value* value) 306 { 307 /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ 308 switch (*column) { 309 case 7: /* tcpConnectionState */ 310 value->u32 = pcb->state + 1; 311 break; 312 case 8: /* tcpConnectionProcess */ 313 value->u32 = 0; /* not supported */ 314 break; 315 default: 316 return SNMP_ERR_NOSUCHINSTANCE; 317 } 318 319 return SNMP_ERR_NOERROR; 320 } 321 322 static snmp_err_t 323 tcp_ConnectionTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) 324 { 325 ip_addr_t local_ip, remote_ip; 326 u16_t local_port, remote_port; 327 struct tcp_pcb *pcb; 328 u8_t idx = 0; 329 u8_t i; 330 struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; 331 332 LWIP_UNUSED_ARG(value_len); 333 334 /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ 335 idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); 336 if (idx == 0) { 337 return SNMP_ERR_NOSUCHINSTANCE; 338 } 339 340 /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ 341 idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &remote_ip, &remote_port); 342 if (idx == 0) { 343 return SNMP_ERR_NOSUCHINSTANCE; 344 } 345 346 /* find tcp_pcb with requested ip and port*/ 347 for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { 348 pcb = *tcp_pcb_nonlisten_lists[i]; 349 350 while (pcb != NULL) { 351 if (ip_addr_cmp(&local_ip, &pcb->local_ip) && 352 (local_port == pcb->local_port) && 353 ip_addr_cmp(&remote_ip, &pcb->remote_ip) && 354 (remote_port == pcb->remote_port)) { 355 /* fill in object properties */ 356 return tcp_ConnectionTable_get_cell_value_core(column, pcb, value); 357 } 358 pcb = pcb->next; 359 } 360 } 361 362 /* not found */ 363 return SNMP_ERR_NOSUCHINSTANCE; 364 } 365 366 static snmp_err_t 367 tcp_ConnectionTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) 368 { 369 struct tcp_pcb *pcb; 370 struct snmp_next_oid_state state; 371 /* 1x tcpConnectionLocalAddressType + 1x OID len + 16x tcpConnectionLocalAddress + 1x tcpConnectionLocalPort 372 * 1x tcpConnectionRemAddressType + 1x OID len + 16x tcpConnectionRemAddress + 1x tcpConnectionRemPort */ 373 u32_t result_temp[38]; 374 u8_t i; 375 struct tcp_pcb ** const tcp_pcb_nonlisten_lists[] = {&tcp_bound_pcbs, &tcp_active_pcbs, &tcp_tw_pcbs}; 376 377 LWIP_UNUSED_ARG(value_len); 378 379 /* init struct to search next oid */ 380 snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); 381 382 /* iterate over all possible OIDs to find the next one */ 383 for (i = 0; i < LWIP_ARRAYSIZE(tcp_pcb_nonlisten_lists); i++) { 384 pcb = *tcp_pcb_nonlisten_lists[i]; 385 386 while (pcb != NULL) { 387 u8_t idx = 0; 388 u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; 389 390 /* tcpConnectionLocalAddressType + tcpConnectionLocalAddress + tcpConnectionLocalPort */ 391 idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); 392 393 /* tcpConnectionRemAddressType + tcpConnectionRemAddress + tcpConnectionRemPort */ 394 idx += snmp_ip_port_to_oid(&pcb->remote_ip, pcb->remote_port, &test_oid[idx]); 395 396 /* check generated OID: is it a candidate for the next one? */ 397 snmp_next_oid_check(&state, test_oid, idx, pcb); 398 399 pcb = pcb->next; 400 } 401 } 402 403 /* did we find a next one? */ 404 if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { 405 snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); 406 /* fill in object properties */ 407 return tcp_ConnectionTable_get_cell_value_core(column, (struct tcp_pcb*)state.reference, value); 408 } else { 409 /* not found */ 410 return SNMP_ERR_NOSUCHINSTANCE; 411 } 412 } 413 414 /* --- tcpListenerTable --- */ 415 416 static snmp_err_t 417 tcp_ListenerTable_get_cell_value_core(const u32_t* column, union snmp_variant_value* value) 418 { 419 /* all items except tcpListenerProcess are declared as not-accessible */ 420 switch (*column) { 421 case 4: /* tcpListenerProcess */ 422 value->u32 = 0; /* not supported */ 423 break; 424 default: 425 return SNMP_ERR_NOSUCHINSTANCE; 426 } 427 428 return SNMP_ERR_NOERROR; 429 } 430 431 static snmp_err_t 432 tcp_ListenerTable_get_cell_value(const u32_t* column, const u32_t* row_oid, u8_t row_oid_len, union snmp_variant_value* value, u32_t* value_len) 433 { 434 ip_addr_t local_ip; 435 u16_t local_port; 436 struct tcp_pcb_listen *pcb; 437 u8_t idx = 0; 438 439 LWIP_UNUSED_ARG(value_len); 440 441 /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ 442 idx += snmp_oid_to_ip_port(&row_oid[idx], row_oid_len-idx, &local_ip, &local_port); 443 if (idx == 0) { 444 return SNMP_ERR_NOSUCHINSTANCE; 445 } 446 447 /* find tcp_pcb with requested ip and port*/ 448 pcb = tcp_listen_pcbs.listen_pcbs; 449 while (pcb != NULL) { 450 if (ip_addr_cmp(&local_ip, &pcb->local_ip) && 451 (local_port == pcb->local_port)) { 452 /* fill in object properties */ 453 return tcp_ListenerTable_get_cell_value_core(column, value); 454 } 455 pcb = pcb->next; 456 } 457 458 /* not found */ 459 return SNMP_ERR_NOSUCHINSTANCE; 460 } 461 462 static snmp_err_t 463 tcp_ListenerTable_get_next_cell_instance_and_value(const u32_t* column, struct snmp_obj_id* row_oid, union snmp_variant_value* value, u32_t* value_len) 464 { 465 struct tcp_pcb_listen *pcb; 466 struct snmp_next_oid_state state; 467 /* 1x tcpListenerLocalAddressType + 1x OID len + 16x tcpListenerLocalAddress + 1x tcpListenerLocalPort */ 468 u32_t result_temp[19]; 469 470 LWIP_UNUSED_ARG(value_len); 471 472 /* init struct to search next oid */ 473 snmp_next_oid_init(&state, row_oid->id, row_oid->len, result_temp, LWIP_ARRAYSIZE(result_temp)); 474 475 /* iterate over all possible OIDs to find the next one */ 476 pcb = tcp_listen_pcbs.listen_pcbs; 477 while (pcb != NULL) { 478 u8_t idx = 0; 479 u32_t test_oid[LWIP_ARRAYSIZE(result_temp)]; 480 481 /* tcpListenerLocalAddressType + tcpListenerLocalAddress + tcpListenerLocalPort */ 482 idx += snmp_ip_port_to_oid(&pcb->local_ip, pcb->local_port, &test_oid[idx]); 483 484 /* check generated OID: is it a candidate for the next one? */ 485 snmp_next_oid_check(&state, test_oid, idx, NULL); 486 487 pcb = pcb->next; 488 } 489 490 /* did we find a next one? */ 491 if (state.status == SNMP_NEXT_OID_STATUS_SUCCESS) { 492 snmp_oid_assign(row_oid, state.next_oid, state.next_oid_len); 493 /* fill in object properties */ 494 return tcp_ListenerTable_get_cell_value_core(column, value); 495 } else { 496 /* not found */ 497 return SNMP_ERR_NOSUCHINSTANCE; 498 } 499 } 500 501 static const struct snmp_scalar_node tcp_RtoAlgorithm = SNMP_SCALAR_CREATE_NODE_READONLY(1, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); 502 static const struct snmp_scalar_node tcp_RtoMin = SNMP_SCALAR_CREATE_NODE_READONLY(2, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); 503 static const struct snmp_scalar_node tcp_RtoMax = SNMP_SCALAR_CREATE_NODE_READONLY(3, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); 504 static const struct snmp_scalar_node tcp_MaxConn = SNMP_SCALAR_CREATE_NODE_READONLY(4, SNMP_ASN1_TYPE_INTEGER, tcp_get_value); 505 static const struct snmp_scalar_node tcp_ActiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(5, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 506 static const struct snmp_scalar_node tcp_PassiveOpens = SNMP_SCALAR_CREATE_NODE_READONLY(6, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 507 static const struct snmp_scalar_node tcp_AttemptFails = SNMP_SCALAR_CREATE_NODE_READONLY(7, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 508 static const struct snmp_scalar_node tcp_EstabResets = SNMP_SCALAR_CREATE_NODE_READONLY(8, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 509 static const struct snmp_scalar_node tcp_CurrEstab = SNMP_SCALAR_CREATE_NODE_READONLY(9, SNMP_ASN1_TYPE_GAUGE, tcp_get_value); 510 static const struct snmp_scalar_node tcp_InSegs = SNMP_SCALAR_CREATE_NODE_READONLY(10, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 511 static const struct snmp_scalar_node tcp_OutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(11, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 512 static const struct snmp_scalar_node tcp_RetransSegs = SNMP_SCALAR_CREATE_NODE_READONLY(12, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 513 static const struct snmp_scalar_node tcp_InErrs = SNMP_SCALAR_CREATE_NODE_READONLY(14, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 514 static const struct snmp_scalar_node tcp_OutRsts = SNMP_SCALAR_CREATE_NODE_READONLY(15, SNMP_ASN1_TYPE_COUNTER, tcp_get_value); 515 static const struct snmp_scalar_node tcp_HCInSegs = SNMP_SCALAR_CREATE_NODE_READONLY(17, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); 516 static const struct snmp_scalar_node tcp_HCOutSegs = SNMP_SCALAR_CREATE_NODE_READONLY(18, SNMP_ASN1_TYPE_COUNTER64, tcp_get_value); 517 518 #if LWIP_IPV4 519 static const struct snmp_table_simple_col_def tcp_ConnTable_columns[] = { 520 { 1, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnState */ 521 { 2, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalAddress */ 522 { 3, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnLocalPort */ 523 { 4, SNMP_ASN1_TYPE_IPADDR, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnRemAddress */ 524 { 5, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnRemPort */ 525 }; 526 527 static const struct snmp_table_simple_node tcp_ConnTable = SNMP_TABLE_CREATE_SIMPLE(13, tcp_ConnTable_columns, tcp_ConnTable_get_cell_value, tcp_ConnTable_get_next_cell_instance_and_value); 528 #endif /* LWIP_IPV4 */ 529 530 static const struct snmp_table_simple_col_def tcp_ConnectionTable_columns[] = { 531 /* all items except tcpConnectionState and tcpConnectionProcess are declared as not-accessible */ 532 { 7, SNMP_ASN1_TYPE_INTEGER, SNMP_VARIANT_VALUE_TYPE_U32 }, /* tcpConnectionState */ 533 { 8, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpConnectionProcess */ 534 }; 535 536 static const struct snmp_table_simple_node tcp_ConnectionTable = SNMP_TABLE_CREATE_SIMPLE(19, tcp_ConnectionTable_columns, tcp_ConnectionTable_get_cell_value, tcp_ConnectionTable_get_next_cell_instance_and_value); 537 538 539 static const struct snmp_table_simple_col_def tcp_ListenerTable_columns[] = { 540 /* all items except tcpListenerProcess are declared as not-accessible */ 541 { 4, SNMP_ASN1_TYPE_UNSIGNED32, SNMP_VARIANT_VALUE_TYPE_U32 } /* tcpListenerProcess */ 542 }; 543 544 static const struct snmp_table_simple_node tcp_ListenerTable = SNMP_TABLE_CREATE_SIMPLE(20, tcp_ListenerTable_columns, tcp_ListenerTable_get_cell_value, tcp_ListenerTable_get_next_cell_instance_and_value); 545 546 /* the following nodes access variables in LWIP stack from SNMP worker thread and must therefore be synced to LWIP (TCPIP) thread */ 547 CREATE_LWIP_SYNC_NODE( 1, tcp_RtoAlgorithm) 548 CREATE_LWIP_SYNC_NODE( 2, tcp_RtoMin) 549 CREATE_LWIP_SYNC_NODE( 3, tcp_RtoMax) 550 CREATE_LWIP_SYNC_NODE( 4, tcp_MaxConn) 551 CREATE_LWIP_SYNC_NODE( 5, tcp_ActiveOpens) 552 CREATE_LWIP_SYNC_NODE( 6, tcp_PassiveOpens) 553 CREATE_LWIP_SYNC_NODE( 7, tcp_AttemptFails) 554 CREATE_LWIP_SYNC_NODE( 8, tcp_EstabResets) 555 CREATE_LWIP_SYNC_NODE( 9, tcp_CurrEstab) 556 CREATE_LWIP_SYNC_NODE(10, tcp_InSegs) 557 CREATE_LWIP_SYNC_NODE(11, tcp_OutSegs) 558 CREATE_LWIP_SYNC_NODE(12, tcp_RetransSegs) 559 #if LWIP_IPV4 560 CREATE_LWIP_SYNC_NODE(13, tcp_ConnTable) 561 #endif /* LWIP_IPV4 */ 562 CREATE_LWIP_SYNC_NODE(14, tcp_InErrs) 563 CREATE_LWIP_SYNC_NODE(15, tcp_OutRsts) 564 CREATE_LWIP_SYNC_NODE(17, tcp_HCInSegs) 565 CREATE_LWIP_SYNC_NODE(18, tcp_HCOutSegs) 566 CREATE_LWIP_SYNC_NODE(19, tcp_ConnectionTable) 567 CREATE_LWIP_SYNC_NODE(20, tcp_ListenerTable) 568 569 static const struct snmp_node* const tcp_nodes[] = { 570 &SYNC_NODE_NAME(tcp_RtoAlgorithm).node.node, 571 &SYNC_NODE_NAME(tcp_RtoMin).node.node, 572 &SYNC_NODE_NAME(tcp_RtoMax).node.node, 573 &SYNC_NODE_NAME(tcp_MaxConn).node.node, 574 &SYNC_NODE_NAME(tcp_ActiveOpens).node.node, 575 &SYNC_NODE_NAME(tcp_PassiveOpens).node.node, 576 &SYNC_NODE_NAME(tcp_AttemptFails).node.node, 577 &SYNC_NODE_NAME(tcp_EstabResets).node.node, 578 &SYNC_NODE_NAME(tcp_CurrEstab).node.node, 579 &SYNC_NODE_NAME(tcp_InSegs).node.node, 580 &SYNC_NODE_NAME(tcp_OutSegs).node.node, 581 &SYNC_NODE_NAME(tcp_RetransSegs).node.node, 582 #if LWIP_IPV4 583 &SYNC_NODE_NAME(tcp_ConnTable).node.node, 584 #endif /* LWIP_IPV4 */ 585 &SYNC_NODE_NAME(tcp_InErrs).node.node, 586 &SYNC_NODE_NAME(tcp_OutRsts).node.node, 587 &SYNC_NODE_NAME(tcp_HCInSegs).node.node, 588 &SYNC_NODE_NAME(tcp_HCOutSegs).node.node, 589 &SYNC_NODE_NAME(tcp_ConnectionTable).node.node, 590 &SYNC_NODE_NAME(tcp_ListenerTable).node.node 591 }; 592 593 const struct snmp_tree_node snmp_mib2_tcp_root = SNMP_CREATE_TREE_NODE(6, tcp_nodes); 594 #endif /* LWIP_SNMP && SNMP_LWIP_MIB2 && LWIP_TCP */ 595