diff options
Diffstat (limited to '3rdparty/openpgm-svn-r1135/pgm/pgmMIB.c')
-rw-r--r-- | 3rdparty/openpgm-svn-r1135/pgm/pgmMIB.c | 3212 |
1 files changed, 3212 insertions, 0 deletions
diff --git a/3rdparty/openpgm-svn-r1135/pgm/pgmMIB.c b/3rdparty/openpgm-svn-r1135/pgm/pgmMIB.c new file mode 100644 index 0000000..1226c50 --- /dev/null +++ b/3rdparty/openpgm-svn-r1135/pgm/pgmMIB.c @@ -0,0 +1,3212 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.notify.conf,v 5.3 2004/04/15 12:29:19 dts12 Exp $ + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include <impl/i18n.h> +#include <impl/framework.h> +#include <impl/receiver.h> +#include <impl/socket.h> + +#include "pgm/snmp.h" +#include "impl/pgmMIB.h" +#include "impl/pgmMIB_columns.h" +#include "impl/pgmMIB_enums.h" + + +//#define PGMMIB_DEBUG + + +/* locals */ + +struct pgm_snmp_context_t { + pgm_slist_t* list; + pgm_list_t* node; + int index; /* table index */ + unsigned instance; /* unique number per node */ +}; + +typedef struct pgm_snmp_context_t pgm_snmp_context_t; + +static const oid snmptrap_oid[] = {1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0}; + + +/* functions */ + +static int initialize_table_pgmSourceTable(void); +static Netsnmp_Node_Handler pgmSourceTable_handler; +static Netsnmp_First_Data_Point pgmSourceTable_get_first_data_point; +static Netsnmp_Next_Data_Point pgmSourceTable_get_next_data_point; +static Netsnmp_Free_Loop_Context pgmSourceTable_free_loop_context; + +static int initialize_table_pgmSourceConfigTable(void); +static Netsnmp_Node_Handler pgmSourceConfigTable_handler; +static Netsnmp_First_Data_Point pgmSourceConfigTable_get_first_data_point; +static Netsnmp_Next_Data_Point pgmSourceConfigTable_get_next_data_point; +static Netsnmp_Free_Loop_Context pgmSourceConfigTable_free_loop_context; + +static int initialize_table_pgmSourcePerformanceTable(void); +static Netsnmp_Node_Handler pgmSourcePerformanceTable_handler; +static Netsnmp_First_Data_Point pgmSourcePerformanceTable_get_first_data_point; +static Netsnmp_Next_Data_Point pgmSourcePerformanceTable_get_next_data_point; +static Netsnmp_Free_Loop_Context pgmSourcePerformanceTable_free_loop_context; + +static int initialize_table_pgmReceiverTable(void); +static Netsnmp_Node_Handler pgmReceiverTable_handler; +static Netsnmp_First_Data_Point pgmReceiverTable_get_first_data_point; +static Netsnmp_Next_Data_Point pgmReceiverTable_get_next_data_point; +static Netsnmp_Free_Loop_Context pgmReceiverTable_free_loop_context; + +static int initialize_table_pgmReceiverConfigTable(void); +static Netsnmp_Node_Handler pgmReceiverConfigTable_handler; +static Netsnmp_First_Data_Point pgmReceiverConfigTable_get_first_data_point; +static Netsnmp_Next_Data_Point pgmReceiverConfigTable_get_next_data_point; +static Netsnmp_Free_Loop_Context pgmReceiverConfigTable_free_loop_context; + +static int initialize_table_pgmReceiverPerformanceTable(void); +static Netsnmp_Node_Handler pgmReceiverPerformanceTable_handler; +static Netsnmp_First_Data_Point pgmReceiverPerformanceTable_get_first_data_point; +static Netsnmp_Next_Data_Point pgmReceiverPerformanceTable_get_next_data_point; +static Netsnmp_Free_Loop_Context pgmReceiverPerformanceTable_free_loop_context; + + +bool +pgm_mib_init ( + pgm_error_t** error + ) +{ + if (MIB_REGISTERED_OK != initialize_table_pgmSourceTable()) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_SNMP, + PGM_ERROR_FAILED, + _("pgmSourceTable registration: see SNMP log for further details.")); + return FALSE; + } + if (MIB_REGISTERED_OK != initialize_table_pgmSourceConfigTable()) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_SNMP, + PGM_ERROR_FAILED, + _("pgmSourceConfigTable registration: see SNMP log for further details.")); + return FALSE; + } + if (MIB_REGISTERED_OK != initialize_table_pgmSourcePerformanceTable()) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_SNMP, + PGM_ERROR_FAILED, + _("pgmSourcePerformanceTable registration: see SNMP log for further details.")); + return FALSE; + } + if (MIB_REGISTERED_OK != initialize_table_pgmReceiverTable()) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_SNMP, + PGM_ERROR_FAILED, + _("pgmReceiverTable registration: see SNMP log for further details.")); + return FALSE; + } + if (MIB_REGISTERED_OK != initialize_table_pgmReceiverConfigTable()) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_SNMP, + PGM_ERROR_FAILED, + _("pgmReceiverConfigTable registration: see SNMP log for further details.")); + return FALSE; + } + if (MIB_REGISTERED_OK != initialize_table_pgmReceiverPerformanceTable()) { + pgm_set_error (error, + PGM_ERROR_DOMAIN_SNMP, + PGM_ERROR_FAILED, + _("pgmReceiverPerformanceTable registration: see SNMP log for further details.")); + return FALSE; + } + + return TRUE; +} + +/* + * pgmSourceTable + * + * returns MIB_REGISTERED_OK on success, failures include: + * MIB_REGISTRATION_FAILED + * MIB_DUPLICATE_REGISTRATION + * SNMPERR_GENERR + */ + +static +int +initialize_table_pgmSourceTable (void) +{ + pgm_debug ("initialize_table_pgmSourceTable ()"); + + static const oid pgmSourceTable_oid[] = {1,3,6,1,3,112,1,2,100,2}; + netsnmp_table_registration_info* table_info = NULL; + netsnmp_iterator_info* iinfo = NULL; + netsnmp_handler_registration* reg = NULL; + + reg = netsnmp_create_handler_registration ("pgmSourceTable", pgmSourceTable_handler, + pgmSourceTable_oid, OID_LENGTH( pgmSourceTable_oid ), + HANDLER_CAN_RONLY); + if (!reg) + goto error; + + table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); + if (!table_info) + goto error; + + table_info->min_column = COLUMN_PGMSOURCESOURCEADDRESS; + table_info->max_column = COLUMN_PGMSOURCESOURCEPORTNUMBER; + + netsnmp_table_helper_add_indexes (table_info, + ASN_OCTET_STR, /* index: pgmSourceGlobalId */ + ASN_UNSIGNED, /* index: pgmSourceSourcePort */ + 0); + + iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info ); + if (!iinfo) + goto error; + + iinfo->get_first_data_point = pgmSourceTable_get_first_data_point; + iinfo->get_next_data_point = pgmSourceTable_get_next_data_point; + iinfo->free_loop_context_at_end = pgmSourceTable_free_loop_context; + iinfo->table_reginfo = table_info; + + return netsnmp_register_table_iterator (reg, iinfo); + +error: + if (table_info && table_info->indexes) /* table_data_free_func() is internal */ + snmp_free_var (table_info->indexes); + SNMP_FREE( table_info ); + SNMP_FREE( iinfo ); + netsnmp_handler_registration_free (reg); + + return -1; +} + +/* called for first row of data in SNMP table + * + * goal is to cache all the relevant data for subsequent get_next_data_point (row) calls in my_loop_context, + * optionally returns my_data_context. + * + * returns answer or NULL + */ + +static +netsnmp_variable_list* +pgmSourceTable_get_first_data_point( + void** my_loop_context, /* valid through one query of multiple "data points" */ + void** my_data_context, /* answer blob which is passed to handler() */ + netsnmp_variable_list* put_index_data, /* answer */ + netsnmp_iterator_info* mydata /* iinfo on init() */ + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_rwlock_reader_lock (&pgm_sock_list_lock); + + if (!pgm_sock_list) { + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + +/* create our own context for this SNMP loop */ + pgm_snmp_context_t* context = pgm_new0 (pgm_snmp_context_t, 1); + context->list = pgm_sock_list; + *my_loop_context = context; + +/* pass on for generic row access */ + return pgmSourceTable_get_next_data_point (my_loop_context, my_data_context, put_index_data, mydata); +} + +static +netsnmp_variable_list* +pgmSourceTable_get_next_data_point( + void** my_loop_context, + void** my_data_context, + netsnmp_variable_list* put_index_data, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourceTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context; + netsnmp_variable_list *idx = put_index_data; + + if (!context->list) + return NULL; + + pgm_sock_t* sock = context->list->data; + +/* pgmSourceGlobalId */ + char gsi[ PGM_GSISTRLEN ]; + pgm_gsi_print_r (&sock->tsi.gsi, gsi, sizeof(gsi)); + snmp_set_var_typed_value (idx, ASN_OCTET_STR, (const u_char*)&gsi, strlen (gsi)); + idx = idx->next_variable; + +/* pgmSourceSourcePort */ + const unsigned sport = ntohs (sock->tsi.sport); + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&sport, sizeof(sport)); + + *my_data_context = sock; + context->list = context->list->next; + + return put_index_data; +} + +static +void +pgmSourceTable_free_loop_context ( + void* my_loop_context, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourceTable_free_loop_context (my_loop_context:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context; + pgm_free (context); + my_loop_context = NULL; + + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); +} + +static +int +pgmSourceTable_handler ( + netsnmp_mib_handler* handler, + netsnmp_handler_registration* reginfo, + netsnmp_agent_request_info* reqinfo, + netsnmp_request_info* requests + ) +{ +/* pre-conditions */ + pgm_assert (NULL != handler); + pgm_assert (NULL != reginfo); + pgm_assert (NULL != reqinfo); + pgm_assert (NULL != requests); + + pgm_debug ("pgmSourceTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)", + (const void*)handler, + (const void*)reginfo, + (const void*)reqinfo, + (const void*)requests); + + switch (reqinfo->mode) { + +/* Read-support (also covers GetNext requests) */ + + case MODE_GET: + for (netsnmp_request_info* request = requests; + request; + request = request->next) + { + const pgm_sock_t* sock = (pgm_sock_t*)netsnmp_extract_iterator_context (request); + + if (!sock) { + netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + + netsnmp_variable_list *var = request->requestvb; + netsnmp_table_request_info* table_info = netsnmp_extract_table_info (request); + + if (!table_info) { + snmp_log (LOG_ERR, "pgmSourceTable_handler: empty table request info.\n"); + continue; + } + + switch (table_info->colnum) { + + case COLUMN_PGMSOURCESOURCEADDRESS: + { + struct sockaddr_in s4; + if (AF_INET == sock->send_gsr.gsr_source.ss_family) + memcpy (&s4, &sock->send_gsr.gsr_source, sizeof(s4)); + else + memset (&s4, 0, sizeof(s4)); + snmp_set_var_typed_value (var, ASN_IPADDRESS, + (const u_char*)&s4.sin_addr.s_addr, + sizeof(struct in_addr) ); + } + break; + + case COLUMN_PGMSOURCEGROUPADDRESS: + { + struct sockaddr_in s4; + if (AF_INET == sock->send_gsr.gsr_group.ss_family) + memcpy (&s4, &sock->send_gsr.gsr_group, sizeof(s4)); + else + memset (&s4, 0, sizeof(s4)); + snmp_set_var_typed_value (var, ASN_IPADDRESS, + (const u_char*)&s4.sin_addr.s_addr, + sizeof(struct in_addr) ); + } + break; + + case COLUMN_PGMSOURCEDESTPORT: + { + const unsigned dport = ntohs (sock->dport); + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&dport, sizeof(dport) ); + } + break; + +/* copy index[0] */ + case COLUMN_PGMSOURCESOURCEGSI: + snmp_set_var_typed_value (var, ASN_OCTET_STR, + (const u_char*)table_info->indexes->val.string, + table_info->indexes->val_len); + break; + +/* copy index[1] */ + case COLUMN_PGMSOURCESOURCEPORTNUMBER: + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)table_info->indexes->next_variable->val.integer, + table_info->indexes->next_variable->val_len); + + break; + + default: + snmp_log (LOG_ERR, "pgmSourceTable_handler: unknown column.\n"); + break; + } + } + break; + + case MODE_SET_RESERVE1: + default: + snmp_log (LOG_ERR, "pgmSourceTable_handler: unsupported mode.\n"); + break; + + } + + return SNMP_ERR_NOERROR; +} + +/* + * pgmSourceConfigTable + * + */ + +static +int +initialize_table_pgmSourceConfigTable(void) +{ + pgm_debug ("initialize_table_pgmSourceConfigTable ()"); + + static const oid pgmSourceConfigTable_oid[] = {1,3,6,1,3,112,1,2,100,3}; + netsnmp_table_registration_info* table_info = NULL; + netsnmp_iterator_info* iinfo = NULL; + netsnmp_handler_registration* reg = NULL; + + reg = netsnmp_create_handler_registration ("pgmSourceConfigTable", pgmSourceConfigTable_handler, + pgmSourceConfigTable_oid, OID_LENGTH( pgmSourceConfigTable_oid ), + HANDLER_CAN_RONLY); + if (!reg) + goto error; + + table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); + if (!table_info) + goto error; + + table_info->min_column = COLUMN_PGMSOURCETTL; + table_info->max_column = COLUMN_PGMSOURCESPMPATHADDRESS; + + netsnmp_table_helper_add_indexes (table_info, + ASN_OCTET_STR, /* index: pgmSourceConfigGlobalId */ + ASN_UNSIGNED, /* index: pgmSourceConfigSourcePort */ + 0); + + iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info ); + if (!iinfo) + goto error; + + iinfo->get_first_data_point = pgmSourceConfigTable_get_first_data_point; + iinfo->get_next_data_point = pgmSourceConfigTable_get_next_data_point; + iinfo->free_loop_context_at_end = pgmSourceConfigTable_free_loop_context; + iinfo->table_reginfo = table_info; + + return netsnmp_register_table_iterator (reg, iinfo); + +error: + if (table_info && table_info->indexes) /* table_data_free_func() is internal */ + snmp_free_var (table_info->indexes); + SNMP_FREE( table_info ); + SNMP_FREE( iinfo ); + netsnmp_handler_registration_free (reg); + + return -1; +} + +/* called for first row of data in SNMP table + * + * goal is to cache all the relevant data for subsequent get_next_data_point (row) calls in my_loop_context, + * optionally returns my_data_context. + * + * returns answer or NULL + */ + +static +netsnmp_variable_list* +pgmSourceConfigTable_get_first_data_point( + void** my_loop_context, /* valid through one query of multiple "data points" */ + void** my_data_context, /* answer blob which is passed to handler() */ + netsnmp_variable_list* put_index_data, /* answer */ + netsnmp_iterator_info* mydata /* iinfo on init() */ + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourceConfigTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_rwlock_reader_lock (&pgm_sock_list_lock); + + if (!pgm_sock_list) { + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + +/* create our own context for this SNMP loop */ + pgm_snmp_context_t* context = pgm_new0 (pgm_snmp_context_t, 1); + context->list = pgm_sock_list; + *my_loop_context = context; + +/* pass on for generic row access */ + return pgmSourceConfigTable_get_next_data_point (my_loop_context, my_data_context, put_index_data, mydata); +} + +static +netsnmp_variable_list* +pgmSourceConfigTable_get_next_data_point( + void** my_loop_context, + void** my_data_context, + netsnmp_variable_list* put_index_data, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourceConfigTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context; + netsnmp_variable_list *idx = put_index_data; + + if (!context->list) + return NULL; + + pgm_sock_t* sock = context->list->data; + +/* pgmSourceGlobalId */ + char gsi[ PGM_GSISTRLEN ]; + pgm_gsi_print_r (&sock->tsi.gsi, gsi, sizeof(gsi)); + snmp_set_var_typed_value (idx, ASN_OCTET_STR, (const u_char*)&gsi, strlen (gsi)); + idx = idx->next_variable; + +/* pgmSourceSourcePort */ + const unsigned sport = ntohs (sock->tsi.sport); + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&sport, sizeof(sport)); + + *my_data_context = sock; + context->list = context->list->next; + + return put_index_data; +} + +static +void +pgmSourceConfigTable_free_loop_context ( + void* my_loop_context, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourceConfigTable_free_loop_context (my_loop_context:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context; + pgm_free (context); + my_loop_context = NULL; + + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); +} + +static +int +pgmSourceConfigTable_handler ( + netsnmp_mib_handler* handler, + netsnmp_handler_registration* reginfo, + netsnmp_agent_request_info* reqinfo, + netsnmp_request_info* requests + ) +{ +/* pre-conditions */ + pgm_assert (NULL != handler); + pgm_assert (NULL != reginfo); + pgm_assert (NULL != reqinfo); + pgm_assert (NULL != requests); + + pgm_debug ("pgmSourceConfigTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)", + (const void*)handler, + (const void*)reginfo, + (const void*)reqinfo, + (const void*)requests); + + switch (reqinfo->mode) { + +/* Read-support (also covers GetNext requests) */ + + case MODE_GET: + for (netsnmp_request_info* request = requests; + request; + request = request->next) + { + const pgm_sock_t* sock = (pgm_sock_t*)netsnmp_extract_iterator_context (request); + + if (!sock) { + netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + + netsnmp_variable_list *var = request->requestvb; + netsnmp_table_request_info* table_info = netsnmp_extract_table_info (request); + + if (!table_info) { + snmp_log (LOG_ERR, "pgmSourceTable_handler: empty table request info.\n"); + continue; + } + + switch (table_info->colnum) { + + case COLUMN_PGMSOURCETTL: + { + const unsigned hops = sock->hops; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&hops, sizeof(hops) ); + } + break; + + case COLUMN_PGMSOURCEADVMODE: + { + const unsigned adv_mode = 0 == sock->adv_mode ? PGMSOURCEADVMODE_TIME : PGMSOURCEADVMODE_DATA; + snmp_set_var_typed_value (var, ASN_INTEGER, + (const u_char*)&adv_mode, sizeof(adv_mode) ); + } + break; + +/* FIXED: pgmSourceLateJoin = disable(2) */ + case COLUMN_PGMSOURCELATEJOIN: + { + const unsigned late_join = PGMSOURCELATEJOIN_DISABLE; + snmp_set_var_typed_value (var, ASN_INTEGER, + (const u_char*)&late_join, sizeof(late_join) ); + } + break; + + case COLUMN_PGMSOURCETXWMAXRTE: + { + const unsigned txw_max_rte = sock->txw_max_rte; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&txw_max_rte, sizeof(txw_max_rte) ); + } + break; + + case COLUMN_PGMSOURCETXWSECS: + { + const unsigned txw_secs = sock->txw_secs; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&txw_secs, sizeof(txw_secs) ); + } + break; + +/* FIXED: TXW_ADV_SECS = 0 */ + case COLUMN_PGMSOURCETXWADVSECS: + { + const unsigned txw_adv_secs = 0; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&txw_adv_secs, sizeof(txw_adv_secs) ); + } + break; + +/* FIXED: pgmSourceAdvIvl = TXW_ADV_SECS * 1000 = 0 */ + case COLUMN_PGMSOURCEADVIVL: + { + const unsigned adv_ivl = 0; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&adv_ivl, sizeof(adv_ivl) ); + } + break; + + case COLUMN_PGMSOURCESPMIVL: + { + const unsigned spm_ivl = pgm_to_msecs (sock->spm_ambient_interval); + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&spm_ivl, sizeof(spm_ivl) ); + } + break; + +/* TODO: IHB_MIN */ + case COLUMN_PGMSOURCESPMHEARTBEATIVLMIN: + { + const unsigned ihb_min = 0; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&ihb_min, sizeof(ihb_min) ); + } + break; + +/* TODO: IHB_MAX */ + case COLUMN_PGMSOURCESPMHEARTBEATIVLMAX: + { + const unsigned ihb_max = 0; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&ihb_max, sizeof(ihb_max) ); + } + break; + +/* NAK_BO_IVL */ + case COLUMN_PGMSOURCERDATABACKOFFIVL: + { + const unsigned nak_bo_ivl = pgm_to_msecs (sock->nak_bo_ivl); + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&nak_bo_ivl, sizeof(nak_bo_ivl) ); + } + break; + +/* FIXED: pgmSourceFEC = disabled(1) */ + case COLUMN_PGMSOURCEFEC: + { + const unsigned fec = (sock->use_ondemand_parity || sock->use_proactive_parity) ? 1 : 0; + snmp_set_var_typed_value (var, ASN_INTEGER, + (const u_char*)&fec, sizeof(fec) ); + } + break; + +/* FIXED: pgmSourceFECTransmissionGrpSize = 0 */ + case COLUMN_PGMSOURCEFECTRANSMISSIONGRPSIZE: + { + const unsigned fec_tgs = sock->rs_k; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&fec_tgs, sizeof(fec_tgs) ); + } + break; + +/* FIXED: pgmSourceFECProactiveParitySize = 0 */ + case COLUMN_PGMSOURCEFECPROACTIVEPARITYSIZE: + { + const unsigned fec_paps = sock->rs_proactive_h; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&fec_paps, sizeof(fec_paps) ); + } + break; + +/* IPv6 not supported */ + case COLUMN_PGMSOURCESPMPATHADDRESS: + { + struct sockaddr_in s4; + if (AF_INET == sock->recv_gsr[0].gsr_source.ss_family) + memcpy (&s4, &sock->recv_gsr[0].gsr_source, sizeof(s4)); + else + memset (&s4, 0, sizeof(s4)); + snmp_set_var_typed_value (var, ASN_IPADDRESS, + (const u_char*)&s4.sin_addr.s_addr, + sizeof(struct in_addr) ); + } + break; + + default: + snmp_log (LOG_ERR, "pgmSourceConfigTable_handler: unknown column.\n"); + break; + } + } + break; + + case MODE_SET_RESERVE1: + default: + snmp_log (LOG_ERR, "pgmSourceConfigTable_handler: unsupported mode.\n"); + break; + + } + + return SNMP_ERR_NOERROR; +} + +/* + * pgmSourcePerformanceTable + */ + +static +int +initialize_table_pgmSourcePerformanceTable (void) +{ + pgm_debug ("initialize_table_pgmSourcePerformanceTable ()"); + + static const oid pgmSourcePerformanceTable_oid[] = {1,3,6,1,3,112,1,2,100,4}; + netsnmp_table_registration_info* table_info = NULL; + netsnmp_iterator_info* iinfo = NULL; + netsnmp_handler_registration* reg = NULL; + + reg = netsnmp_create_handler_registration ("pgmSourcePerformanceTable", pgmSourcePerformanceTable_handler, + pgmSourcePerformanceTable_oid, OID_LENGTH( pgmSourcePerformanceTable_oid ), + HANDLER_CAN_RONLY); + if (!reg) + goto error; + + table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); + if (!table_info) + goto error; + + table_info->min_column = COLUMN_PGMSOURCEDATABYTESSENT; + table_info->max_column = COLUMN_PGMSOURCENNAKERRORS; + + netsnmp_table_helper_add_indexes (table_info, + ASN_OCTET_STR, /* index: pgmSourceGlobalId */ + ASN_UNSIGNED, /* index: pgmSourceSourcePort */ + 0); + + iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info ); + if (!iinfo) + goto error; + + iinfo->get_first_data_point = pgmSourcePerformanceTable_get_first_data_point; + iinfo->get_next_data_point = pgmSourcePerformanceTable_get_next_data_point; + iinfo->free_loop_context_at_end = pgmSourcePerformanceTable_free_loop_context; + iinfo->table_reginfo = table_info; + + return netsnmp_register_table_iterator (reg, iinfo); + +error: + if (table_info && table_info->indexes) /* table_data_free_func() is internal */ + snmp_free_var (table_info->indexes); + SNMP_FREE( table_info ); + SNMP_FREE( iinfo ); + netsnmp_handler_registration_free (reg); + + return -1; +} + +/* called for first row of data in SNMP table + * + * goal is to cache all the relevant data for subsequent get_next_data_point (row) calls in my_loop_context, + * optionally returns my_data_context. + * + * returns answer or NULL + */ + +static +netsnmp_variable_list* +pgmSourcePerformanceTable_get_first_data_point ( + void** my_loop_context, /* valid through one query of multiple "data points" */ + void** my_data_context, /* answer blob which is passed to handler() */ + netsnmp_variable_list* put_index_data, /* answer */ + netsnmp_iterator_info* mydata /* iinfo on init() */ + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourcePerformanceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_rwlock_reader_lock (&pgm_sock_list_lock); + + if (!pgm_sock_list) { + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + +/* create our own context for this SNMP loop */ + pgm_snmp_context_t* context = pgm_new0 (pgm_snmp_context_t, 1); + context->list = pgm_sock_list; + *my_loop_context = context; + +/* pass on for generic row access */ + return pgmSourcePerformanceTable_get_next_data_point (my_loop_context, my_data_context, put_index_data, mydata); +} + +static +netsnmp_variable_list* +pgmSourcePerformanceTable_get_next_data_point ( + void** my_loop_context, + void** my_data_context, + netsnmp_variable_list* put_index_data, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmSourcePerformanceTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context; + netsnmp_variable_list *idx = put_index_data; + + if (!context->list) + return NULL; + + pgm_sock_t* sock = context->list->data; + +/* pgmSourceGlobalId */ + char gsi[ PGM_GSISTRLEN ]; + pgm_gsi_print_r (&sock->tsi.gsi, gsi, sizeof(gsi)); + snmp_set_var_typed_value (idx, ASN_OCTET_STR, (const u_char*)&gsi, strlen (gsi)); + idx = idx->next_variable; + +/* pgmSourceSourcePort */ + const unsigned sport = ntohs (sock->tsi.sport); + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&sport, sizeof(sport)); + + *my_data_context = sock; + context->list = context->list->next; + + return put_index_data; +} + +static +void +pgmSourcePerformanceTable_free_loop_context ( + void* my_loop_context, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmPerformanceSourceTable_free_loop_context (my_loop_context:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context; + pgm_free (context); + my_loop_context = NULL; + + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); +} + +static +int +pgmSourcePerformanceTable_handler ( + netsnmp_mib_handler* handler, + netsnmp_handler_registration* reginfo, + netsnmp_agent_request_info* reqinfo, + netsnmp_request_info* requests + ) +{ +/* pre-conditions */ + pgm_assert (NULL != handler); + pgm_assert (NULL != reginfo); + pgm_assert (NULL != reqinfo); + pgm_assert (NULL != requests); + + pgm_debug ("pgmSourcePerformanceTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)", + (const void*)handler, + (const void*)reginfo, + (const void*)reqinfo, + (const void*)requests); + + switch (reqinfo->mode) { + +/* Read-support (also covers GetNext requests) */ + + case MODE_GET: + for (netsnmp_request_info* request = requests; + request; + request = request->next) + { + const pgm_sock_t* sock = (pgm_sock_t*)netsnmp_extract_iterator_context (request); + + if (!sock) { + netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + + const pgm_txw_t* window = (const pgm_txw_t*)sock->window; + + netsnmp_variable_list *var = request->requestvb; + netsnmp_table_request_info* table_info = netsnmp_extract_table_info (request); + + if (!table_info) { + snmp_log (LOG_ERR, "pgmSourceTable_handler: empty table request info.\n"); + continue; + } + + switch (table_info->colnum) { + + case COLUMN_PGMSOURCEDATABYTESSENT: + { + const unsigned data_bytes = sock->cumulative_stats[PGM_PC_SOURCE_DATA_BYTES_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&data_bytes, sizeof(data_bytes) ); + } + break; + + case COLUMN_PGMSOURCEDATAMSGSSENT: + { + const unsigned data_msgs = sock->cumulative_stats[PGM_PC_SOURCE_DATA_MSGS_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&data_msgs, sizeof(data_msgs) ); + } + break; + + case COLUMN_PGMSOURCEBYTESBUFFERED: + { + const unsigned bytes_buffered = sock->can_send_data ? pgm_txw_size (window) : 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&bytes_buffered, sizeof(bytes_buffered) ); + } + break; + + case COLUMN_PGMSOURCEMSGSBUFFERED: + { + const unsigned msgs_buffered = sock->can_send_data ? pgm_txw_length (window) : 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&msgs_buffered, sizeof(msgs_buffered) ); + } + break; + +/* PGM_PC_SOURCE_SELECTIVE_BYTES_RETRANSMITTED + COLUMN_PGMSOURCEPARITYBYTESRETRANSMITTED */ + case COLUMN_PGMSOURCEBYTESRETRANSMITTED: + { + const unsigned bytes_resent = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_BYTES_RETRANSMITTED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&bytes_resent, sizeof(bytes_resent) ); + } + break; + +/* PGM_PC_SOURCE_SELECTIVE_MSGS_RETRANSMITTED + COLUMN_PGMSOURCEPARITYMSGSRETRANSMITTED */ + case COLUMN_PGMSOURCEMSGSRETRANSMITTED: + { + const unsigned msgs_resent = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_MSGS_RETRANSMITTED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&msgs_resent, sizeof(msgs_resent) ); + } + break; + + case COLUMN_PGMSOURCEBYTESSENT: + { + const unsigned bytes_sent = sock->cumulative_stats[PGM_PC_SOURCE_BYTES_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&bytes_sent, sizeof(bytes_sent) ); + } + break; + +/* COLUMN_PGMSOURCEPARITYNAKPACKETSRECEIVED + COLUMN_PGMSOURCESELECTIVENAKPACKETSRECEIVED */ + case COLUMN_PGMSOURCERAWNAKSRECEIVED: + { + const unsigned nak_packets = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&nak_packets, sizeof(nak_packets) ); + } + break; + +/* PGM_PC_SOURCE_SELECTIVE_NAKS_IGNORED + COLUMN_PGMSOURCEPARITYNAKSIGNORED */ + case COLUMN_PGMSOURCENAKSIGNORED: + { + const unsigned naks_ignored = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_IGNORED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_ignored, sizeof(naks_ignored) ); + } + break; + + case COLUMN_PGMSOURCECKSUMERRORS: + { + const unsigned cksum_errors = sock->cumulative_stats[PGM_PC_SOURCE_CKSUM_ERRORS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&cksum_errors, sizeof(cksum_errors) ); + } + break; + + case COLUMN_PGMSOURCEMALFORMEDNAKS: + { + const unsigned malformed_naks = sock->cumulative_stats[PGM_PC_SOURCE_MALFORMED_NAKS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&malformed_naks, sizeof(malformed_naks) ); + } + break; + + case COLUMN_PGMSOURCEPACKETSDISCARDED: + { + const unsigned packets_discarded = sock->cumulative_stats[PGM_PC_SOURCE_PACKETS_DISCARDED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&packets_discarded, sizeof(packets_discarded) ); + } + break; + +/* PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED + COLUMN_PGMSOURCEPARITYNAKSRECEIVED */ + case COLUMN_PGMSOURCENAKSRCVD: + { + const unsigned naks_received = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_received, sizeof(naks_received) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEPARITYBYTESRETRANSMITTED: + { + const unsigned parity_bytes_resent = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_bytes_resent, sizeof(parity_bytes_resent) ); + } + break; + + case COLUMN_PGMSOURCESELECTIVEBYTESRETRANSMITED: + { + const unsigned selective_bytes_resent = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_BYTES_RETRANSMITTED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&selective_bytes_resent, sizeof(selective_bytes_resent) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEPARITYMSGSRETRANSMITTED: + { + const unsigned parity_msgs_resent = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_msgs_resent, sizeof(parity_msgs_resent) ); + } + break; + + case COLUMN_PGMSOURCESELECTIVEMSGSRETRANSMITTED: + { + const unsigned selective_msgs_resent = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_MSGS_RETRANSMITTED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&selective_msgs_resent, sizeof(selective_msgs_resent) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEBYTESADMIT: + { + const unsigned bytes_admit = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&bytes_admit, sizeof(bytes_admit) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEMSGSADMIT: + { + const unsigned msgs_admit = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&msgs_admit, sizeof(msgs_admit) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEPARITYNAKPACKETSRECEIVED: + { + const unsigned parity_nak_packets = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_nak_packets, sizeof(parity_nak_packets) ); + } + break; + + case COLUMN_PGMSOURCESELECTIVENAKPACKETSRECEIVED: + { + const unsigned selective_nak_packets = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&selective_nak_packets, sizeof(selective_nak_packets) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEPARITYNAKSRECEIVED: + { + const unsigned parity_naks = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_naks, sizeof(parity_naks) ); + } + break; + + case COLUMN_PGMSOURCESELECTIVENAKSRECEIVED: + { + const unsigned selective_naks = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&selective_naks, sizeof(selective_naks) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEPARITYNAKSIGNORED: + { + const unsigned parity_naks_ignored = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_naks_ignored, sizeof(parity_naks_ignored) ); + } + break; + + case COLUMN_PGMSOURCESELECTIVENAKSIGNORED: + { + const unsigned selective_naks_ignored = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_IGNORED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&selective_naks_ignored, sizeof(selective_naks_ignored) ); + } + break; + + case COLUMN_PGMSOURCEACKERRORS: + { + const unsigned ack_errors = sock->cumulative_stats[PGM_PC_SOURCE_ACK_ERRORS];; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&ack_errors, sizeof(ack_errors) ); + } + break; + + case COLUMN_PGMSOURCEPGMCCACKER: + { + struct sockaddr_in s4; + if (AF_INET == sock->acker_nla.ss_family) + memcpy (&s4, &sock->acker_nla, sizeof(s4)); + else + memset (&s4, 0, sizeof(s4)); + snmp_set_var_typed_value (var, ASN_IPADDRESS, + (const u_char*)&s4.sin_addr.s_addr, + sizeof(struct in_addr) ); + } + break; + + case COLUMN_PGMSOURCETRANSMISSIONCURRENTRATE: + { + const unsigned tx_current_rate = sock->cumulative_stats[PGM_PC_SOURCE_TRANSMISSION_CURRENT_RATE]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&tx_current_rate, sizeof(tx_current_rate) ); + } + break; + + case COLUMN_PGMSOURCEACKPACKETSRECEIVED: + { + const unsigned ack_packets = sock->cumulative_stats[PGM_PC_SOURCE_ACK_PACKETS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&ack_packets, sizeof(ack_packets) ); + } + break; + +/* COLUMN_PGMSOURCEPARITYNNAKPACKETSRECEIVED + COLUMN_PGMSOURCESELECTIVENNAKPACKETSRECEIVED */ + case COLUMN_PGMSOURCENNAKPACKETSRECEIVED: + { + const unsigned nnak_packets = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAK_PACKETS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&nnak_packets, sizeof(nnak_packets) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEPARITYNNAKPACKETSRECEIVED: + { + const unsigned parity_nnak_packets = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_nnak_packets, sizeof(parity_nnak_packets) ); + } + break; + + case COLUMN_PGMSOURCESELECTIVENNAKPACKETSRECEIVED: + { + const unsigned selective_nnak_packets = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAK_PACKETS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&selective_nnak_packets, sizeof(selective_nnak_packets) ); + } + break; + +/* COLUMN_PGMSOURCEPARITYNNAKSRECEIVED + COLUMN_PGMSOURCESELECTIVENNAKSRECEIVED */ + case COLUMN_PGMSOURCENNAKSRECEIVED: + { + const unsigned nnaks_received = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAKS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&nnaks_received, sizeof(nnaks_received) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMSOURCEPARITYNNAKSRECEIVED: + { + const unsigned parity_nnaks = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_nnaks, sizeof(parity_nnaks) ); + } + break; + + case COLUMN_PGMSOURCESELECTIVENNAKSRECEIVED: + { + const unsigned selective_nnaks = sock->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAKS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&selective_nnaks, sizeof(selective_nnaks) ); + } + break; + + case COLUMN_PGMSOURCENNAKERRORS: + { + const unsigned malformed_nnaks = sock->cumulative_stats[PGM_PC_SOURCE_NNAK_ERRORS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&malformed_nnaks, sizeof(malformed_nnaks) ); + } + break; + + default: + snmp_log (LOG_ERR, "pgmSourcePerformanceTable_handler: unknown column.\n"); + break; + } + } + break; + + case MODE_SET_RESERVE1: + default: + snmp_log (LOG_ERR, "pgmSourcePerformanceTable_handler: unsupported mode.\n"); + break; + + } + + return SNMP_ERR_NOERROR; +} + +/* + * pgmReceiverTable + */ + +static +int +initialize_table_pgmReceiverTable(void) +{ + pgm_debug ("initialize_table_pgmReceiverTable ()"); + + static const oid pgmReceiverTable_oid[] = {1,3,6,1,3,112,1,3,100,2}; + netsnmp_table_registration_info* table_info = NULL; + netsnmp_iterator_info* iinfo = NULL; + netsnmp_handler_registration* reg = NULL; + + reg = netsnmp_create_handler_registration ("pgmReceiverTable", pgmReceiverTable_handler, + pgmReceiverTable_oid, OID_LENGTH( pgmReceiverTable_oid ), + HANDLER_CAN_RONLY); + if (!reg) + goto error; + + table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); + if (!table_info) + goto error; + + table_info->min_column = COLUMN_PGMRECEIVERGROUPADDRESS; + table_info->max_column = COLUMN_PGMRECEIVERUNIQUEINSTANCE; + + netsnmp_table_helper_add_indexes (table_info, + ASN_OCTET_STR, /* index: pgmReceiverGlobalId */ + ASN_UNSIGNED, /* index: pgmReceiverSourcePort */ + ASN_UNSIGNED, /* index: pgmReceiverInstance */ + 0); + + iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info ); + if (!iinfo) + goto error; + + iinfo->get_first_data_point = pgmReceiverTable_get_first_data_point; + iinfo->get_next_data_point = pgmReceiverTable_get_next_data_point; + iinfo->free_loop_context_at_end = pgmReceiverTable_free_loop_context; + iinfo->table_reginfo = table_info; + + return netsnmp_register_table_iterator (reg, iinfo); + +error: + if (table_info && table_info->indexes) /* table_data_free_func() is internal */ + snmp_free_var (table_info->indexes); + SNMP_FREE( table_info ); + SNMP_FREE( iinfo ); + netsnmp_handler_registration_free (reg); + + return -1; +} + +/* called for first row of data in SNMP table + * + * goal is to cache all the relevant data for subsequent get_next_data_point (row) calls in my_loop_context, + * optionally returns my_data_context. + * + * returns answer or NULL + */ + +static +netsnmp_variable_list* +pgmReceiverTable_get_first_data_point ( + void** my_loop_context, /* valid through one query of multiple "data points" */ + void** my_data_context, /* answer blob which is passed to handler() */ + netsnmp_variable_list* put_index_data, /* answer */ + netsnmp_iterator_info* mydata /* iinfo on init() */ + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_rwlock_reader_lock (&pgm_sock_list_lock); + + if (!pgm_sock_list) { + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + +/* create our own context for this SNMP loop */ + pgm_snmp_context_t* context = pgm_new0 (pgm_snmp_context_t, 1); + +/* hunt to find first node, through all socks */ + for (context->list = pgm_sock_list; + context->list; + context->list = context->list->next) + { +/* and through all peers for each sock */ + pgm_sock_t* sock = (pgm_sock_t*)context->list->data; + pgm_rwlock_reader_lock (&sock->peers_lock); + context->node = sock->peers_list; + if (context->node) { +/* maintain this sock's peers lock */ + break; + } + + pgm_rwlock_reader_unlock (&sock->peers_lock); + } + +/* no node found */ + if (!context->node) { + pgm_free (context); + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + + *my_loop_context = context; + +/* pass on for generic row access */ + return pgmReceiverTable_get_next_data_point (my_loop_context, my_data_context, put_index_data, mydata); +} + +static +netsnmp_variable_list* +pgmReceiverTable_get_next_data_point ( + void** my_loop_context, + void** my_data_context, + netsnmp_variable_list* put_index_data, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context; + netsnmp_variable_list *idx = put_index_data; + + if (!context->list) + return NULL; + + pgm_sock_t* sock = context->list->data; + + if (!context->node) + return NULL; + + pgm_peer_t* peer = context->node->data; + +/* pgmReceiverGlobalId */ + char gsi[ PGM_GSISTRLEN ]; + pgm_gsi_print_r (&peer->tsi.gsi, gsi, sizeof(gsi)); + snmp_set_var_typed_value (idx, ASN_OCTET_STR, (const u_char*)&gsi, strlen (gsi)); + idx = idx->next_variable; + +/* pgmReceiverSourcePort */ + const unsigned sport = ntohs (peer->tsi.sport); + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&sport, sizeof(sport)); + idx = idx->next_variable; + +/* pgmReceiverInstance */ + const unsigned instance = context->instance++; + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&instance, sizeof(instance)); + +/* set data context to pass to handler callback */ + *my_data_context = peer; + +/* hunt for next valid node */ + if (context->node->next) { + context->node = context->node->next; + } else { + context->node = NULL; + while (context->list->next) + { + pgm_rwlock_reader_unlock (&sock->peers_lock); + context->list = context->list->next; + sock = context->list->data; + pgm_rwlock_reader_lock (&sock->peers_lock); + context->node = sock->peers_list; + if (context->node) { +/* keep lock */ + break; + } + } + } + + return put_index_data; +} + +static +void +pgmReceiverTable_free_loop_context ( + void* my_loop_context, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverTable_free_loop_context (my_loop_context:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context; + +/* check for intra-peer state */ + if (context->list) { + pgm_sock_t* sock = context->list->data; + pgm_rwlock_reader_unlock (&sock->peers_lock); + } + + pgm_free (context); + my_loop_context = NULL; + + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); +} + +static +int +pgmReceiverTable_handler ( + netsnmp_mib_handler* handler, + netsnmp_handler_registration* reginfo, + netsnmp_agent_request_info* reqinfo, + netsnmp_request_info* requests + ) +{ +/* pre-conditions */ + pgm_assert (NULL != handler); + pgm_assert (NULL != reginfo); + pgm_assert (NULL != reqinfo); + pgm_assert (NULL != requests); + + pgm_debug ("pgmReceiverTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)", + (const void*)handler, + (const void*)reginfo, + (const void*)reqinfo, + (const void*)requests); + + switch (reqinfo->mode) { + +/* Read-support (also covers GetNext requests) */ + + case MODE_GET: + for (netsnmp_request_info* request = requests; + request; + request = request->next) + { + const pgm_peer_t* peer = (pgm_peer_t*)netsnmp_extract_iterator_context (request); + + if (!peer) { + netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + + netsnmp_variable_list *var = request->requestvb; + netsnmp_table_request_info* table_info = netsnmp_extract_table_info(request); + + if (table_info == NULL) { + snmp_log (LOG_ERR, "pgmReceiverTable_handler: empty table request info.\n"); + continue; + } + + switch (table_info->colnum) { + + case COLUMN_PGMRECEIVERGROUPADDRESS: + { + struct sockaddr_in s4; + if (AF_INET == peer->group_nla.ss_family) + memcpy (&s4, &peer->group_nla, sizeof(s4)); + else + memset (&s4, 0, sizeof(s4)); + snmp_set_var_typed_value (var, ASN_IPADDRESS, + (const u_char*)&s4.sin_addr.s_addr, + sizeof(struct in_addr) ); + } + break; + +/* by definition same as sock */ + case COLUMN_PGMRECEIVERDESTPORT: + { + const unsigned dport = ntohs (peer->sock->dport); + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&dport, sizeof(dport) ); + } + break; + + case COLUMN_PGMRECEIVERSOURCEADDRESS: + { + struct sockaddr_in s4; + if (AF_INET == peer->nla.ss_family) + memcpy (&s4, &peer->nla, sizeof(s4)); + else + memset (&s4, 0, sizeof(s4)); + snmp_set_var_typed_value (var, ASN_IPADDRESS, + (const u_char*)&s4.sin_addr.s_addr, + sizeof(struct in_addr) ); + } + break; + + case COLUMN_PGMRECEIVERLASTHOP: + { + struct sockaddr_in s4; + if (AF_INET == peer->local_nla.ss_family) + memcpy (&s4, &peer->local_nla, sizeof(s4)); + else + memset (&s4, 0, sizeof(s4)); + snmp_set_var_typed_value (var, ASN_IPADDRESS, + (const u_char*)&s4.sin_addr.s_addr, + sizeof(struct in_addr) ); + } + break; + +/* copy index[0] */ + case COLUMN_PGMRECEIVERSOURCEGSI: + snmp_set_var_typed_value (var, ASN_OCTET_STR, + (const u_char*)table_info->indexes->val.string, + table_info->indexes->val_len); + break; + +/* copy index[1] */ + case COLUMN_PGMRECEIVERSOURCEPORTNUMBER: + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)table_info->indexes->next_variable->val.integer, + table_info->indexes->next_variable->val_len); + break; + +/* copy index[2] */ + case COLUMN_PGMRECEIVERUNIQUEINSTANCE: + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)table_info->indexes->next_variable->next_variable->val.integer, + table_info->indexes->next_variable->next_variable->val_len); + break; + + default: + snmp_log (LOG_ERR, "pgmReceiverTable_handler: unknown column.\n"); + break; + } + } + break; + + case MODE_SET_RESERVE1: + default: + snmp_log (LOG_ERR, "pgmReceiverTable_handler: unsupported mode.\n"); + break; + + } + + return SNMP_ERR_NOERROR; +} + +/* + * pgmReceiverConfigTable + * + */ + +static +int +initialize_table_pgmReceiverConfigTable(void) +{ + pgm_debug ("initialize_table_pgmReceiverConfigTable ()"); + + static const oid pgmReceiverConfigTable_oid[] = {1,3,6,1,3,112,1,3,100,3}; + netsnmp_table_registration_info* table_info = NULL; + netsnmp_iterator_info* iinfo = NULL; + netsnmp_handler_registration* reg = NULL; + + reg = netsnmp_create_handler_registration ("pgmReceiverConfigTable", pgmReceiverConfigTable_handler, + pgmReceiverConfigTable_oid, OID_LENGTH(pgmReceiverConfigTable_oid), + HANDLER_CAN_RONLY); + if (!reg) + goto error; + + table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); + if (!table_info) + goto error; + + table_info->min_column = COLUMN_PGMRECEIVERNAKBACKOFFIVL; + table_info->max_column = COLUMN_PGMRECEIVERNAKFAILURETHRESHOLD; + + netsnmp_table_helper_add_indexes (table_info, + ASN_OCTET_STR, /* index: pgmReceiverConfigGlobalId */ + ASN_UNSIGNED, /* index: pgmReceiverConfigSourcePort */ + ASN_UNSIGNED, /* index: pgmReceiverInstance */ + 0); + + iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info ); + if (!iinfo) + goto error; + + iinfo->get_first_data_point = pgmReceiverConfigTable_get_first_data_point; + iinfo->get_next_data_point = pgmReceiverConfigTable_get_next_data_point; + iinfo->free_loop_context_at_end = pgmReceiverConfigTable_free_loop_context; + iinfo->table_reginfo = table_info; + + return netsnmp_register_table_iterator (reg, iinfo); + +error: + if (table_info && table_info->indexes) /* table_data_free_func() is internal */ + snmp_free_var (table_info->indexes); + SNMP_FREE( table_info ); + SNMP_FREE( iinfo ); + netsnmp_handler_registration_free (reg); + + return -1; +} + +/* called for first row of data in SNMP table + * + * goal is to cache all the relevant data for subsequent get_next_data_point (row) calls in my_loop_context, + * optionally returns my_data_context. + * + * returns answer or NULL + */ + +static +netsnmp_variable_list* +pgmReceiverConfigTable_get_first_data_point( + void** my_loop_context, /* valid through one query of multiple "data points" */ + void** my_data_context, /* answer blob which is passed to handler() */ + netsnmp_variable_list* put_index_data, /* answer */ + netsnmp_iterator_info* mydata /* iinfo on init() */ + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverConfigTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_rwlock_reader_lock (&pgm_sock_list_lock); + + if (!pgm_sock_list) { + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + +/* create our own context for this SNMP loop */ + pgm_snmp_context_t* context = pgm_new0 (pgm_snmp_context_t, 1); + +/* hunt to find first node, through all socks */ + for (context->list = pgm_sock_list; + context->list; + context->list = context->list->next) + { +/* and through all peers for each sock */ + pgm_sock_t* sock = (pgm_sock_t*)context->list->data; + pgm_rwlock_reader_lock (&sock->peers_lock); + context->node = sock->peers_list; + if (context->node) + break; + + pgm_rwlock_reader_unlock (&sock->peers_lock); + } + +/* no node found */ + if (!context->node) { + pgm_free (context); + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + + *my_loop_context = context; + +/* pass on for generic row access */ + return pgmReceiverConfigTable_get_next_data_point (my_loop_context, my_data_context, put_index_data, mydata); +} + +static +netsnmp_variable_list* +pgmReceiverConfigTable_get_next_data_point( + void** my_loop_context, + void** my_data_context, + netsnmp_variable_list* put_index_data, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverConfigTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context; + netsnmp_variable_list *idx = put_index_data; + + if (!context->list) + return NULL; + + pgm_sock_t* sock = context->list->data; + + if (!context->node) + return NULL; + + pgm_peer_t* peer = context->node->data; + +/* pgmReceiverGlobalId */ + char gsi[ PGM_GSISTRLEN ]; + pgm_gsi_print_r (&peer->tsi.gsi, gsi, sizeof(gsi)); + snmp_set_var_typed_value (idx, ASN_OCTET_STR, (const u_char*)&gsi, strlen (gsi)); + idx = idx->next_variable; + +/* pgmReceiverSourcePort */ + const unsigned sport = ntohs (peer->tsi.sport); + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&sport, sizeof(sport)); + idx = idx->next_variable; + +/* pgmReceiverInstance */ + const unsigned instance = context->instance++; + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&instance, sizeof(instance)); + +/* set data context to pass to handler callback */ + *my_data_context = peer; + +/* hunt for next valid node */ + if (context->node->next) { + context->node = context->node->next; + } else { + context->node = NULL; + while (context->list->next) + { + pgm_rwlock_reader_unlock (&sock->peers_lock); + context->list = context->list->next; + sock = context->list->data; + pgm_rwlock_reader_lock (&sock->peers_lock); + context->node = sock->peers_list; + if (context->node) { +/* keep lock */ + break; + } + } + } + + return put_index_data; +} + +static +void +pgmReceiverConfigTable_free_loop_context ( + void* my_loop_context, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverConfigTable_free_loop_context (my_loop_context:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context; + +/* check for intra-peer state */ + if (context->list) { + pgm_sock_t* sock = context->list->data; + pgm_rwlock_reader_unlock (&sock->peers_lock); + } + + pgm_free (context); + my_loop_context = NULL; + + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); +} + +static +int +pgmReceiverConfigTable_handler ( + netsnmp_mib_handler* handler, + netsnmp_handler_registration* reginfo, + netsnmp_agent_request_info* reqinfo, + netsnmp_request_info* requests + ) +{ +/* pre-conditions */ + pgm_assert (NULL != handler); + pgm_assert (NULL != reginfo); + pgm_assert (NULL != reqinfo); + pgm_assert (NULL != requests); + + pgm_debug ("pgmReceiverConfigTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)", + (const void*)handler, + (const void*)reginfo, + (const void*)reqinfo, + (const void*)requests); + + switch (reqinfo->mode) { + +/* Read-support (also covers GetNext requests) */ + + case MODE_GET: + for (netsnmp_request_info* request = requests; + request; + request = request->next) + { + const pgm_peer_t* peer = (pgm_peer_t*)netsnmp_extract_iterator_context(request); + + if (peer == NULL) { + netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + + netsnmp_variable_list *var = request->requestvb; + netsnmp_table_request_info* table_info = netsnmp_extract_table_info(request); + + if (table_info == NULL) { + snmp_log (LOG_ERR, "pgmReceiverTable_handler: empty table request info.\n"); + continue; + } + + switch (table_info->colnum) { + +/* nak_bo_ivl from sock */ + case COLUMN_PGMRECEIVERNAKBACKOFFIVL: + { + const unsigned nak_bo_ivl = peer->sock->nak_bo_ivl; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&nak_bo_ivl, sizeof(nak_bo_ivl) ); + } + break; + +/* nak_rpt_ivl from sock */ + case COLUMN_PGMRECEIVERNAKREPEATIVL: + { + const unsigned nak_rpt_ivl = peer->sock->nak_rpt_ivl; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&nak_rpt_ivl, sizeof(nak_rpt_ivl) ); + } + break; + +/* nak_ncf_retries from sock */ + case COLUMN_PGMRECEIVERNAKNCFRETRIES: + { + const unsigned nak_ncf_retries = peer->sock->nak_ncf_retries; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&nak_ncf_retries, sizeof(nak_ncf_retries) ); + } + break; + +/* nak_rdata_ivl from sock */ + case COLUMN_PGMRECEIVERNAKRDATAIVL: + { + const unsigned nak_rdata_ivl = peer->sock->nak_rdata_ivl; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&nak_rdata_ivl, sizeof(nak_rdata_ivl) ); + } + break; + +/* nak_data_retries from sock */ + case COLUMN_PGMRECEIVERNAKDATARETRIES: + { + const unsigned nak_data_retries = peer->sock->nak_data_retries; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&nak_data_retries, sizeof(nak_data_retries) ); + } + break; + +/* FIXED: pgmReceiverSendNaks = enabled(1) */ + case COLUMN_PGMRECEIVERSENDNAKS: + { + const unsigned send_naks = PGMRECEIVERSENDNAKS_ENABLED; + snmp_set_var_typed_value (var, ASN_INTEGER, + (const u_char*)&send_naks, sizeof(send_naks) ); + } + break; + +/* FIXED: pgmReceiverLateJoin = disabled(2) */ + case COLUMN_PGMRECEIVERLATEJOIN: + { + const unsigned late_join = PGMRECEIVERLATEJOIN_DISABLED; + snmp_set_var_typed_value (var, ASN_INTEGER, + (const u_char*)&late_join, sizeof(late_join) ); + } + break; + +/* FIXED: 1 for multicast */ + case COLUMN_PGMRECEIVERNAKTTL: + { + const unsigned nak_hops = 1; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&nak_hops, sizeof(nak_hops) ); + } + break; + +/* FIXED: pgmReceiverDeliveryOrder = ordered(2) */ + case COLUMN_PGMRECEIVERDELIVERYORDER: + { + const unsigned delivery_order = PGMRECEIVERDELIVERYORDER_ORDERED; + snmp_set_var_typed_value (var, ASN_INTEGER, + (const u_char*)&delivery_order, sizeof(delivery_order) ); + } + break; + +/* FIXED: pgmReceiverMcastNaks = disabled(2) */ + case COLUMN_PGMRECEIVERMCASTNAKS: + { + const unsigned mcast_naks = PGMRECEIVERMCASTNAKS_DISABLED; + snmp_set_var_typed_value (var, ASN_INTEGER, + (const u_char*)&mcast_naks, sizeof(mcast_naks) ); + } + break; + +/* TODO: traps */ + case COLUMN_PGMRECEIVERNAKFAILURETHRESHOLDTIMER: + case COLUMN_PGMRECEIVERNAKFAILURETHRESHOLD: + { + const unsigned threshold = 0; + snmp_set_var_typed_value (var, ASN_UNSIGNED, + (const u_char*)&threshold, sizeof(threshold) ); + } + break; + + default: + snmp_log (LOG_ERR, "pgmReceiverTable_handler: unknown column.\n"); + break; + } + } + break; + + case MODE_SET_RESERVE1: + default: + snmp_log (LOG_ERR, "pgmReceiverTable_handler: unsupported mode.\n"); + break; + + } + + return SNMP_ERR_NOERROR; +} + +/* + * pgmReceiverPerformanceTable + */ + +static +int +initialize_table_pgmReceiverPerformanceTable (void) +{ + pgm_debug ("initialize_table_pgmReceiverPerformanceTable ()"); + + static const oid pgmReceiverPerformanceTable_oid[] = {1,3,6,1,3,112,1,3,100,4}; + netsnmp_table_registration_info* table_info = NULL; + netsnmp_iterator_info* iinfo = NULL; + netsnmp_handler_registration* reg = NULL; + + reg = netsnmp_create_handler_registration ("pgmReceiverPerformanceTable", pgmReceiverPerformanceTable_handler, + pgmReceiverPerformanceTable_oid, OID_LENGTH( pgmReceiverPerformanceTable_oid ), + HANDLER_CAN_RONLY); + if (!reg) + goto error; + + table_info = SNMP_MALLOC_TYPEDEF( netsnmp_table_registration_info ); + if (!table_info) + goto error; + + table_info->min_column = COLUMN_PGMRECEIVERDATABYTESRECEIVED; + table_info->max_column = COLUMN_PGMRECEIVERLASTINTERVALNAKFAILURES; + + netsnmp_table_helper_add_indexes (table_info, + ASN_OCTET_STR, /* index: pgmReceiverGlobalId */ + ASN_UNSIGNED, /* index: pgmReceiverSourcePort */ + ASN_UNSIGNED, /* index: pgmReceiverInstance */ + 0); + + iinfo = SNMP_MALLOC_TYPEDEF( netsnmp_iterator_info ); + if (!iinfo) + goto error; + + iinfo->get_first_data_point = pgmReceiverPerformanceTable_get_first_data_point; + iinfo->get_next_data_point = pgmReceiverPerformanceTable_get_next_data_point; + iinfo->free_loop_context_at_end = pgmReceiverPerformanceTable_free_loop_context; + iinfo->table_reginfo = table_info; + + return netsnmp_register_table_iterator (reg, iinfo); + +error: + if (table_info && table_info->indexes) /* table_data_free_func() is internal */ + snmp_free_var (table_info->indexes); + SNMP_FREE( table_info ); + SNMP_FREE( iinfo ); + netsnmp_handler_registration_free (reg); + + return -1; +} + +/* called for first row of data in SNMP table + * + * goal is to cache all the relevant data for subsequent get_next_data_point (row) calls in my_loop_context, + * optionally returns my_data_context. + * + * returns answer or NULL + */ + +static +netsnmp_variable_list* +pgmReceiverPerformanceTable_get_first_data_point ( + void** my_loop_context, /* valid through one query of multiple "data points" */ + void** my_data_context, /* answer blob which is passed to handler() */ + netsnmp_variable_list* put_index_data, /* answer */ + netsnmp_iterator_info* mydata /* iinfo on init() */ + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverPerformanceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_rwlock_reader_lock (&pgm_sock_list_lock); + + if (!pgm_sock_list) { + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + +/* create our own context for this SNMP loop */ + pgm_snmp_context_t* context = pgm_new0 (pgm_snmp_context_t, 1); + +/* hunt to find first node, through all socks */ + for (context->list = pgm_sock_list; + context->list; + context->list = context->list->next) + { +/* and through all peers for each sock */ + pgm_sock_t* sock = (pgm_sock_t*)context->list->data; + pgm_rwlock_reader_lock (&sock->peers_lock); + context->node = sock->peers_list; + if (context->node) + break; + + pgm_rwlock_reader_unlock (&sock->peers_lock); + } + +/* no node found */ + if (!context->node) { + pgm_free (context); + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); + return NULL; + } + + *my_loop_context = context; + +/* pass on for generic row access */ + return pgmReceiverPerformanceTable_get_next_data_point (my_loop_context, my_data_context, put_index_data, mydata); +} + +static +netsnmp_variable_list* +pgmReceiverPerformanceTable_get_next_data_point ( + void** my_loop_context, + void** my_data_context, + netsnmp_variable_list* put_index_data, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != my_data_context); + pgm_assert (NULL != put_index_data); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverPerformanceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)my_data_context, + (const void*)put_index_data, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context; + netsnmp_variable_list *idx = put_index_data; + + if (!context->list) + return NULL; + + pgm_sock_t* sock = context->list->data; + + if (!context->node) + return NULL; + + pgm_peer_t* peer = context->node->data; + +/* pgmReceiverGlobalId */ + char gsi[ PGM_GSISTRLEN ]; + pgm_gsi_print_r (&peer->tsi.gsi, gsi, sizeof(gsi)); + snmp_set_var_typed_value (idx, ASN_OCTET_STR, (const u_char*)&gsi, strlen (gsi)); + idx = idx->next_variable; + +/* pgmReceiverSourcePort */ + const unsigned sport = ntohs (peer->tsi.sport); + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&sport, sizeof(sport)); + idx = idx->next_variable; + +/* pgmReceiverInstance */ + const unsigned instance = context->instance++; + snmp_set_var_typed_value (idx, ASN_UNSIGNED, (const u_char*)&instance, sizeof(instance)); + +/* set data context to pass to handler callback */ + *my_data_context = peer; + +/* hunt for next valid node */ + if (context->node->next) { + context->node = context->node->next; + } else { + context->node = NULL; + while (context->list->next) + { + pgm_rwlock_reader_unlock (&sock->peers_lock); + context->list = context->list->next; + sock = context->list->data; + pgm_rwlock_reader_lock (&sock->peers_lock); + context->node = sock->peers_list; + + if (context->node) + break; + } + } + + return put_index_data; +} + +static +void +pgmReceiverPerformanceTable_free_loop_context ( + void* my_loop_context, + netsnmp_iterator_info* mydata + ) +{ +/* pre-conditions */ + pgm_assert (NULL != my_loop_context); + pgm_assert (NULL != mydata); + + pgm_debug ("pgmReceiverPerformanceTable_free_loop_context (my_loop_context:%p mydata:%p)", + (const void*)my_loop_context, + (const void*)mydata); + + pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context; + +/* check for intra-peer state */ + if (context->list) { + pgm_sock_t* sock = context->list->data; + pgm_rwlock_reader_unlock (&sock->peers_lock); + } + + pgm_free (context); + my_loop_context = NULL; + + pgm_rwlock_reader_unlock (&pgm_sock_list_lock); +} + +static +int +pgmReceiverPerformanceTable_handler ( + netsnmp_mib_handler* handler, + netsnmp_handler_registration* reginfo, + netsnmp_agent_request_info* reqinfo, + netsnmp_request_info* requests + ) +{ +/* pre-conditions */ + pgm_assert (NULL != handler); + pgm_assert (NULL != reginfo); + pgm_assert (NULL != reqinfo); + pgm_assert (NULL != requests); + + pgm_debug ("pgmReceiverPerformanceTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)", + (const void*)handler, + (const void*)reginfo, + (const void*)reqinfo, + (const void*)requests); + + switch (reqinfo->mode) { + +/* Read-support (also covers GetNext requests) */ + + case MODE_GET: + for (netsnmp_request_info* request = requests; + request; + request = request->next) + { + const pgm_peer_t* peer = (pgm_peer_t*)netsnmp_extract_iterator_context (request); + + if (!peer) { + netsnmp_set_request_error (reqinfo, request, SNMP_NOSUCHINSTANCE); + continue; + } + + const pgm_rxw_t* window = (const pgm_rxw_t*)peer->window; + + netsnmp_variable_list *var = request->requestvb; + netsnmp_table_request_info* table_info = netsnmp_extract_table_info (request); + + if (!table_info) { + snmp_log (LOG_ERR, "pgmReceiverTable_handler: empty table request info.\n"); + continue; + } + + switch (table_info->colnum) { + + case COLUMN_PGMRECEIVERDATABYTESRECEIVED: + { + const unsigned data_bytes = peer->cumulative_stats[PGM_PC_RECEIVER_DATA_BYTES_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&data_bytes, sizeof(data_bytes) ); + } + break; + + case COLUMN_PGMRECEIVERDATAMSGSRECEIVED: + { + const unsigned data_msgs = peer->cumulative_stats[PGM_PC_RECEIVER_DATA_MSGS_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&data_msgs, sizeof(data_msgs) ); + } + break; + +/* total */ + case COLUMN_PGMRECEIVERNAKSSENT: + { + const unsigned naks_sent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_sent, sizeof(naks_sent) ); + } + break; + +/* total */ + case COLUMN_PGMRECEIVERNAKSRETRANSMITTED: + { + const unsigned naks_resent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_RETRANSMITTED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_resent, sizeof(naks_resent) ); + } + break; + +/* total */ + case COLUMN_PGMRECEIVERNAKFAILURES: + { + const unsigned nak_failures = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_FAILED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&nak_failures, sizeof(nak_failures) ); + } + break; + + case COLUMN_PGMRECEIVERBYTESRECEIVED: + { + const unsigned bytes_received = peer->cumulative_stats[PGM_PC_RECEIVER_BYTES_RECEIVED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&bytes_received, sizeof(bytes_received) ); + } + break; + +/* total */ + case COLUMN_PGMRECEIVERNAKSSUPPRESSED: + { + const unsigned naks_suppressed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SUPPRESSED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_suppressed, sizeof(naks_suppressed) ); + } + break; + +/* bogus: same as source checksum errors */ + case COLUMN_PGMRECEIVERCKSUMERRORS: + { + const unsigned cksum_errors = peer->sock->cumulative_stats[PGM_PC_SOURCE_CKSUM_ERRORS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&cksum_errors, sizeof(cksum_errors) ); + } + break; + + case COLUMN_PGMRECEIVERMALFORMEDSPMS: + { + const unsigned malformed_spms = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_SPMS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&malformed_spms, sizeof(malformed_spms) ); + } + break; + + case COLUMN_PGMRECEIVERMALFORMEDODATA: + { + const unsigned malformed_odata = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_ODATA]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&malformed_odata, sizeof(malformed_odata) ); + } + break; + + case COLUMN_PGMRECEIVERMALFORMEDRDATA: + { + const unsigned malformed_rdata = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_RDATA]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&malformed_rdata, sizeof(malformed_rdata) ); + } + break; + + case COLUMN_PGMRECEIVERMALFORMEDNCFS: + { + const unsigned malformed_ncfs = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_NCFS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&malformed_ncfs, sizeof(malformed_ncfs) ); + } + break; + + case COLUMN_PGMRECEIVERPACKETSDISCARDED: + { + const unsigned packets_discarded = peer->cumulative_stats[PGM_PC_RECEIVER_PACKETS_DISCARDED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&packets_discarded, sizeof(packets_discarded) ); + } + break; + + case COLUMN_PGMRECEIVERLOSSES: + { + const unsigned losses = window->cumulative_losses; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&losses, sizeof(losses) ); + } + break; + + case COLUMN_PGMRECEIVERBYTESDELIVEREDTOAPP: + { + const unsigned bytes_delivered =window->bytes_delivered; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&bytes_delivered, sizeof(bytes_delivered) ); + } + break; + + case COLUMN_PGMRECEIVERMSGSDELIVEREDTOAPP: + { + const unsigned msgs_delivered = window->msgs_delivered; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&msgs_delivered, sizeof(msgs_delivered) ); + } + break; + + case COLUMN_PGMRECEIVERDUPSPMS: + { + const unsigned dup_spms = peer->cumulative_stats[PGM_PC_RECEIVER_DUP_SPMS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&dup_spms, sizeof(dup_spms) ); + } + break; + + case COLUMN_PGMRECEIVERDUPDATAS: + { + const unsigned dup_data = peer->cumulative_stats[PGM_PC_RECEIVER_DUP_DATAS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&dup_data, sizeof(dup_data) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMRECEIVERDUPPARITIES: + { + const unsigned dup_parity = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&dup_parity, sizeof(dup_parity) ); + } + break; + +/* COLUMN_PGMRECEIVERPARITYNAKPACKETSSENT + COLUMN_PGMRECEIVERSELECTIVENAKPACKETSSENT */ + case COLUMN_PGMRECEIVERNAKPACKETSSENT: + { + const unsigned nak_packets = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAK_PACKETS_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&nak_packets, sizeof(nak_packets) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMRECEIVERPARITYNAKPACKETSSENT: + { + const unsigned parity_naks = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_naks, sizeof(parity_naks) ); + } + break; + + case COLUMN_PGMRECEIVERSELECTIVENAKPACKETSSENT: + { + const unsigned nak_packets = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAK_PACKETS_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&nak_packets, sizeof(nak_packets) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMRECEIVERPARITYNAKSSENT: + { + const unsigned parity_naks = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_naks, sizeof(parity_naks) ); + } + break; + + case COLUMN_PGMRECEIVERSELECTIVENAKSSENT: + { + const unsigned naks_sent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_sent, sizeof(naks_sent) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMRECEIVERPARITYNAKSRETRANSMITTED: + { + const unsigned parity_resent = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_resent, sizeof(parity_resent) ); + } + break; + + case COLUMN_PGMRECEIVERSELECTIVENAKSRETRANSMITTED: + { + const unsigned naks_resent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_RETRANSMITTED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_resent, sizeof(naks_resent) ); + } + break; + +/* COLUMN_PGMRECEIVERPARITYNAKSFAILED + COLUMN_PGMRECEIVERSELECTIVENAKSFAILED */ + case COLUMN_PGMRECEIVERNAKSFAILED: + { + const unsigned naks_failed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_FAILED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_failed, sizeof(naks_failed) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMRECEIVERPARITYNAKSFAILED: + { + const unsigned parity_failed = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&parity_failed, sizeof(parity_failed) ); + } + break; + + case COLUMN_PGMRECEIVERSELECTIVENAKSFAILED: + { + const unsigned naks_failed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_FAILED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&naks_failed, sizeof(naks_failed) ); + } + break; + + case COLUMN_PGMRECEIVERNAKSFAILEDRXWADVANCED: + { + const unsigned rxw_failed = peer->cumulative_stats[PGM_PC_RECEIVER_NAKS_FAILED_RXW_ADVANCED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&rxw_failed, sizeof(rxw_failed) ); + } + break; + + case COLUMN_PGMRECEIVERNAKSFALEDNCFRETRIESEXCEEDED: + { + const unsigned ncf_retries = peer->cumulative_stats[PGM_PC_RECEIVER_NAKS_FAILED_NCF_RETRIES_EXCEEDED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&ncf_retries, sizeof(ncf_retries) ); + } + break; + + case COLUMN_PGMRECEIVERNAKSFAILEDDATARETRIESEXCEEDED: + { + const unsigned data_retries = peer->cumulative_stats[PGM_PC_RECEIVER_NAKS_FAILED_DATA_RETRIES_EXCEEDED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&data_retries, sizeof(data_retries) ); + } + break; + +/* FIXED: 0 - absolutely no idea what this means */ + case COLUMN_PGMRECEIVERNAKSFAILEDGENEXPIRED: + { + const unsigned happy_pandas = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&happy_pandas, sizeof(happy_pandas) ); + } + break; + + case COLUMN_PGMRECEIVERNAKFAILURESDELIVERED: + { + const unsigned delivered = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_FAILURES_DELIVERED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&delivered, sizeof(delivered) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMRECEIVERPARITYNAKSSUPPRESSED: + { + const unsigned suppressed = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&suppressed, sizeof(suppressed) ); + } + break; + + case COLUMN_PGMRECEIVERSELECTIVENAKSSUPPRESSED: + { + const unsigned suppressed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SUPPRESSED]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&suppressed, sizeof(suppressed) ); + } + break; + + case COLUMN_PGMRECEIVERNAKERRORS: + { + const unsigned malformed_naks = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_ERRORS]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&malformed_naks, sizeof(malformed_naks) ); + } + break; + +/* FIXED: 0 */ + case COLUMN_PGMRECEIVEROUTSTANDINGPARITYNAKS: + { + const unsigned outstanding_parity = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&outstanding_parity, sizeof(outstanding_parity) ); + } + break; + + case COLUMN_PGMRECEIVEROUTSTANDINGSELECTIVENAKS: + { + const unsigned outstanding_selective = window->nak_backoff_queue.length + + window->wait_ncf_queue.length + + window->wait_data_queue.length; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&outstanding_selective, sizeof(outstanding_selective) ); + } + break; + + case COLUMN_PGMRECEIVERLASTACTIVITY: + { + union { + unsigned uint_value; + time_t time_t_value; + } last_activity; + pgm_time_since_epoch (&peer->last_packet, &last_activity.time_t_value); + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&last_activity.uint_value, sizeof(last_activity.uint_value) ); + } + break; + + case COLUMN_PGMRECEIVERNAKSVCTIMEMIN: + { + const unsigned min_repair_time = window->min_fill_time; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&min_repair_time, sizeof(min_repair_time) ); + } + break; + + case COLUMN_PGMRECEIVERNAKSVCTIMEMEAN: + { + const unsigned mean_repair_time = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_SVC_TIME_MEAN]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&mean_repair_time, sizeof(mean_repair_time) ); + } + break; + + case COLUMN_PGMRECEIVERNAKSVCTIMEMAX: + { + const unsigned max_repair_time = window->max_fill_time; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&max_repair_time, sizeof(max_repair_time) ); + } + break; + + case COLUMN_PGMRECEIVERNAKFAILTIMEMIN: + { + const unsigned min_fail_time = peer->min_fail_time; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&min_fail_time, sizeof(min_fail_time) ); + } + break; + + case COLUMN_PGMRECEIVERNAKFAILTIMEMEAN: + { + const unsigned mean_fail_time = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_FAIL_TIME_MEAN]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&mean_fail_time, sizeof(mean_fail_time) ); + } + break; + + case COLUMN_PGMRECEIVERNAKFAILTIMEMAX: + { + const unsigned max_fail_time = peer->max_fail_time; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&max_fail_time, sizeof(max_fail_time) ); + } + break; + + case COLUMN_PGMRECEIVERNAKTRANSMITMIN: + { + const unsigned min_transmit_count = window->min_nak_transmit_count; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&min_transmit_count, sizeof(min_transmit_count) ); + } + break; + + case COLUMN_PGMRECEIVERNAKTRANSMITMEAN: + { + const unsigned mean_transmit_count = peer->cumulative_stats[PGM_PC_RECEIVER_TRANSMIT_MEAN]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&mean_transmit_count, sizeof(mean_transmit_count) ); + } + break; + + case COLUMN_PGMRECEIVERNAKTRANSMITMAX: + { + const unsigned max_transmit_count = window->max_nak_transmit_count; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&max_transmit_count, sizeof(max_transmit_count) ); + } + break; + + case COLUMN_PGMRECEIVERACKSSENT: + { + const unsigned acks_sent = peer->cumulative_stats[PGM_PC_RECEIVER_ACKS_SENT]; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&acks_sent, sizeof(acks_sent) ); + } + break; + + case COLUMN_PGMRECEIVERRXWTRAIL: + { + const unsigned rxw_trail = window->rxw_trail; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&rxw_trail, sizeof(rxw_trail) ); + } + break; + + case COLUMN_PGMRECEIVERRXWLEAD: + { + const unsigned rxw_lead = window->lead; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&rxw_lead, sizeof(rxw_lead) ); + } + break; + +/* TODO: traps */ + case COLUMN_PGMRECEIVERNAKFAILURESLASTINTERVAL: + case COLUMN_PGMRECEIVERLASTINTERVALNAKFAILURES: + { + const unsigned failures = 0; + snmp_set_var_typed_value (var, ASN_COUNTER, /* ASN_COUNTER32 */ + (const u_char*)&failures, sizeof(failures) ); + } + break; + + default: + snmp_log (LOG_ERR, "pgmReceiverTable_handler: unknown column.\n"); + break; + } + } + break; + + case MODE_SET_RESERVE1: + default: + snmp_log (LOG_ERR, "pgmReceiverTable_handler: unsupported mode.\n"); + break; + + } + + return SNMP_ERR_NOERROR; +} + +/* + * SNMP TRAPS + */ + +int +send_pgmStart_trap (void) +{ + pgm_debug ("send_pgmStart_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmStart_oid[] = { 1,3,6,1,3,112,2,0,1 }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH( snmptrap_oid ), + ASN_OBJECT_ID, + (const u_char*)pgmStart_oid, sizeof(pgmStart_oid)); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmStop_trap (void) +{ + pgm_debug ("send_pgmStop_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmStop_oid[] = { 1,3,6,1,3,112,2,0,2 }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmStop_oid, sizeof(pgmStop_oid)); + + +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmNewSourceTrap_trap (void) +{ + pgm_debug ("send_pgmNewSourceTrap_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmNewSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,3 }; + static const oid pgmSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,2,100,2,1,6, /* insert index here */ }; + static const oid pgmSourceSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,2,100,2,1,7, /* insert index here */ }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmNewSourceTrap_oid, sizeof(pgmNewSourceTrap_oid)); +/* + * Add any objects from the trap definition + */ + snmp_varlist_add_variable (&var_list, + pgmSourceSourceGsi_oid, OID_LENGTH(pgmSourceSourceGsi_oid), + ASN_OCTET_STR, +/* Set an appropriate value for pgmSourceSourceGsi */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmSourceSourcePortNumber_oid, OID_LENGTH(pgmSourceSourcePortNumber_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmSourceSourcePortNumber */ + NULL, 0); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmClosedSourceTrap_trap (void) +{ + pgm_debug ("send_pgmClosedSourceTrap_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmClosedSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,4 }; + static const oid pgmSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,2,100,2,1,6, /* insert index here */ }; + static const oid pgmSourceSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,2,100,2,1,7, /* insert index here */ }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmClosedSourceTrap_oid, sizeof(pgmClosedSourceTrap_oid)); +/* + * Add any objects from the trap definition + */ + snmp_varlist_add_variable (&var_list, + pgmSourceSourceGsi_oid, OID_LENGTH(pgmSourceSourceGsi_oid), + ASN_OCTET_STR, +/* Set an appropriate value for pgmSourceSourceGsi */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmSourceSourcePortNumber_oid, OID_LENGTH(pgmSourceSourcePortNumber_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmSourceSourcePortNumber */ + NULL, 0); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmNewReceiverTrap_trap (void) +{ + pgm_debug ("send_pgmNewReceiverTrap_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmNewReceiverTrap_oid[] = { 1,3,6,1,3,112,2,0,5 }; + static const oid pgmReceiverSourceGsi_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,8, /* insert index here */ }; + static const oid pgmReceiverSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,9, /* insert index here */ }; + static const oid pgmReceiverUniqueInstance_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,10, /* insert index here */ }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmNewReceiverTrap_oid, sizeof(pgmNewReceiverTrap_oid)); +/* + * Add any objects from the trap definition + */ + snmp_varlist_add_variable (&var_list, + pgmReceiverSourceGsi_oid, OID_LENGTH(pgmReceiverSourceGsi_oid), + ASN_OCTET_STR, +/* Set an appropriate value for pgmReceiverSourceGsi */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverSourcePortNumber_oid, OID_LENGTH(pgmReceiverSourcePortNumber_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverSourcePortNumber */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverUniqueInstance_oid, OID_LENGTH(pgmReceiverUniqueInstance_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverUniqueInstance */ + NULL, 0); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmClosedReceiverTrap_trap (void) +{ + pgm_debug ("send_pgmClosedReceiverTrap_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmClosedReceiverTrap_oid[] = { 1,3,6,1,3,112,2,0,6 }; + static const oid pgmReceiverSourceGsi_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,8, /* insert index here */ }; + static const oid pgmReceiverSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,9, /* insert index here */ }; + static const oid pgmReceiverUniqueInstance_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,10, /* insert index here */ }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmClosedReceiverTrap_oid, sizeof(pgmClosedReceiverTrap_oid)); +/* + * Add any objects from the trap definition + */ + snmp_varlist_add_variable (&var_list, + pgmReceiverSourceGsi_oid, OID_LENGTH(pgmReceiverSourceGsi_oid), + ASN_OCTET_STR, +/* Set an appropriate value for pgmReceiverSourceGsi */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverSourcePortNumber_oid, OID_LENGTH(pgmReceiverSourcePortNumber_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverSourcePortNumber */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverUniqueInstance_oid, OID_LENGTH(pgmReceiverUniqueInstance_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverUniqueInstance */ + NULL, 0); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmNakFailuresTrap_trap (void) +{ + pgm_debug ("send_pgmNakFailuresTrap_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmNakFailuresTrap_oid[] = { 1,3,6,1,3,112,2,0,7 }; + static const oid pgmReceiverSourceGsi_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,8, /* insert index here */ }; + static const oid pgmReceiverSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,9, /* insert index here */ }; + static const oid pgmReceiverUniqueInstance_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,10, /* insert index here */ }; + static const oid pgmReceiverNakFailureThresholdTimer_oid[] = { 1,3,6,1,3,112,1,3,100,3,1,14, /* insert index here */ }; + static const oid pgmReceiverNakFailureThreshold_oid[] = { 1,3,6,1,3,112,1,3,100,3,1,15, /* insert index here */ }; + static const oid pgmReceiverNakFailuresLastInterval_oid[] = { 1,3,6,1,3,112,1,3,100,4,1,56, /* insert index here */ }; + static const oid pgmReceiverLastIntervalNakFailures_oid[] = { 1,3,6,1,3,112,1,3,100,4,1,57, /* insert index here */ }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmNakFailuresTrap_oid, sizeof(pgmNakFailuresTrap_oid)); +/* + * Add any objects from the trap definition + */ + snmp_varlist_add_variable (&var_list, + pgmReceiverSourceGsi_oid, OID_LENGTH(pgmReceiverSourceGsi_oid), + ASN_OCTET_STR, +/* Set an appropriate value for pgmReceiverSourceGsi */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverSourcePortNumber_oid, OID_LENGTH(pgmReceiverSourcePortNumber_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverSourcePortNumber */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverUniqueInstance_oid, OID_LENGTH(pgmReceiverUniqueInstance_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverUniqueInstance */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverNakFailureThresholdTimer_oid, OID_LENGTH(pgmReceiverNakFailureThresholdTimer_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverNakFailureThresholdTimer */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverNakFailureThreshold_oid, OID_LENGTH(pgmReceiverNakFailureThreshold_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmReceiverNakFailureThreshold */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverNakFailuresLastInterval_oid, OID_LENGTH(pgmReceiverNakFailuresLastInterval_oid), + ASN_COUNTER, +/* Set an appropriate value for pgmReceiverNakFailuresLastInterval */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmReceiverLastIntervalNakFailures_oid, OID_LENGTH(pgmReceiverLastIntervalNakFailures_oid), + ASN_COUNTER, +/* Set an appropriate value for pgmReceiverLastIntervalNakFailures */ + NULL, 0); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmNewDlrSourceTrap_trap (void) +{ + pgm_debug ("send_pgmNewDlrSourceTrap_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmNewDlrSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,8 }; + static const oid pgmDlrSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,4,100,2,1,4, /* insert index here */ }; + static const oid pgmDlrSourceSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,4,100,2,1,5, /* insert index here */ }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmNewDlrSourceTrap_oid, sizeof(pgmNewDlrSourceTrap_oid)); +/* + * Add any objects from the trap definition + */ + snmp_varlist_add_variable (&var_list, + pgmDlrSourceSourceGsi_oid, OID_LENGTH(pgmDlrSourceSourceGsi_oid), + ASN_OCTET_STR, +/* Set an appropriate value for pgmDlrSourceSourceGsi */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmDlrSourceSourcePortNumber_oid, OID_LENGTH(pgmDlrSourceSourcePortNumber_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmDlrSourceSourcePortNumber */ + NULL, 0); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +int +send_pgmClosedDlrSourceTrap_trap (void) +{ + pgm_debug ("send_pgmClosedDlrSourceTrap_trap ()"); + + netsnmp_variable_list *var_list = NULL; + static const oid pgmClosedDlrSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,9 }; + static const oid pgmDlrSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,4,100,2,1,4, /* insert index here */ }; + static const oid pgmDlrSourceSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,4,100,2,1,5, /* insert index here */ }; + +/* + * Set the snmpTrapOid.0 value + */ + snmp_varlist_add_variable (&var_list, + snmptrap_oid, OID_LENGTH(snmptrap_oid), + ASN_OBJECT_ID, + (const u_char*)pgmClosedDlrSourceTrap_oid, sizeof(pgmClosedDlrSourceTrap_oid)); + +/* + * Add any objects from the trap definition + */ + snmp_varlist_add_variable (&var_list, + pgmDlrSourceSourceGsi_oid, OID_LENGTH(pgmDlrSourceSourceGsi_oid), + ASN_OCTET_STR, +/* Set an appropriate value for pgmDlrSourceSourceGsi */ + NULL, 0); + snmp_varlist_add_variable (&var_list, + pgmDlrSourceSourcePortNumber_oid, OID_LENGTH(pgmDlrSourceSourcePortNumber_oid), + ASN_UNSIGNED, +/* Set an appropriate value for pgmDlrSourceSourcePortNumber */ + NULL, 0); +/* + * Add any extra (optional) objects here + */ + +/* + * Send the trap to the list of configured destinations + * and clean up + */ + send_v2trap (var_list); + snmp_free_varbind (var_list); + return SNMP_ERR_NOERROR; +} + +/* eof */ |