Logo Search packages:      
Sourcecode: zeromq version File versions  Download package

pgmMIB.c

/*
 * 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 <glib.h>
#include <glib/gi18n-lib.h>

#include "pgm/snmp.h"
#include "pgm/pgmMIB.h"
#include "pgm/pgmMIB_columns.h"
#include "pgm/pgmMIB_enums.h"
#include "pgm/txwi.h"
#include "pgm/rxwi.h"
#include "pgm/transport.h"


//#define PGMMIB_DEBUG

#ifndef PGMMIB_DEBUG
#define g_trace(...)          while (0)
#else
#define g_trace(...)          g_debug(__VA_ARGS__)
#endif


struct pgm_snmp_context_t {
      GSList*           list;
      GList*            node;
      gint        index;            /* table index */
      unsigned    instance;   /* unique number per node */
};

typedef struct pgm_snmp_context_t pgm_snmp_context_t;


/* local globals */

static 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;


gboolean
pgm_mib_init (
      GError**    error
      )
{
      g_trace ("pgm_mib_init (error:%p)",
            (gpointer)error);

      if (MIB_REGISTERED_OK != initialize_table_pgmSourceTable()) {
            g_set_error (error,
                       PGM_SNMP_ERROR,
                       PGM_SNMP_ERROR_FAILED,
                       _("pgmSourceTable registration: see SNMP log for further details."));
            return FALSE;
      }
      if (MIB_REGISTERED_OK != initialize_table_pgmSourceConfigTable()) {
            g_set_error (error,
                       PGM_SNMP_ERROR,
                       PGM_SNMP_ERROR_FAILED,
                       _("pgmSourceConfigTable registration: see SNMP log for further details."));
            return FALSE;
      }
      if (MIB_REGISTERED_OK != initialize_table_pgmSourcePerformanceTable()) {
            g_set_error (error,
                       PGM_SNMP_ERROR,
                       PGM_SNMP_ERROR_FAILED,
                       _("pgmSourcePerformanceTable registration: see SNMP log for further details."));
            return FALSE;
      }
      if (MIB_REGISTERED_OK != initialize_table_pgmReceiverTable()) {
            g_set_error (error,
                       PGM_SNMP_ERROR,
                       PGM_SNMP_ERROR_FAILED,
                       _("pgmReceiverTable registration: see SNMP log for further details."));
            return FALSE;
      }
      if (MIB_REGISTERED_OK != initialize_table_pgmReceiverConfigTable()) {
            g_set_error (error,
                       PGM_SNMP_ERROR,
                       PGM_SNMP_ERROR_FAILED,
                       _("pgmReceiverConfigTable registration: see SNMP log for further details."));
            return FALSE;
      }
      if (MIB_REGISTERED_OK != initialize_table_pgmReceiverPerformanceTable()) {
            g_set_error (error,
                       PGM_SNMP_ERROR,
                       PGM_SNMP_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)
{
      g_trace ("initialize_table_pgmSourceTable ()");

      static 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 */
      g_assert (NULL != my_loop_context);
      g_assert (NULL != my_data_context);
      g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

      g_trace ("pgmSourceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
            (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      g_static_rw_lock_reader_lock (&pgm_transport_list_lock);

      if (pgm_transport_list == NULL) {
            g_static_rw_lock_reader_unlock (&pgm_transport_list_lock);
            return NULL;
      }

/* create our own context for this SNMP loop */
      pgm_snmp_context_t* context = g_malloc0 (sizeof(pgm_snmp_context_t));
      context->list = pgm_transport_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 */
      g_assert (NULL != my_loop_context);
      g_assert (NULL != my_data_context);
      g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

      g_trace ("pgmSourceTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
            (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context;
      netsnmp_variable_list *idx = put_index_data;

      if ( context->list == NULL )
      {
            return NULL;
      }

      pgm_transport_t* transport = context->list->data;

/* pgmSourceGlobalId */
      char gsi[sizeof("000" "000" "000" "000" "000" "000")];
      snprintf(gsi, sizeof(gsi), "%hhu%hhu%hhu%hhu%hhu%hhu",
            transport->tsi.gsi.identifier[0],
            transport->tsi.gsi.identifier[1],
            transport->tsi.gsi.identifier[2],
            transport->tsi.gsi.identifier[3],
            transport->tsi.gsi.identifier[4],
            transport->tsi.gsi.identifier[5]);
      snmp_set_var_typed_value( idx, ASN_OCTET_STR, (u_char*)&gsi, strlen(gsi) );
      idx = idx->next_variable;

/* pgmSourceSourcePort */
      unsigned sport = g_ntohs (transport->tsi.sport);
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (u_char*)&sport, sizeof(sport) );

      *my_data_context = transport;
      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 */
      g_assert (NULL != my_loop_context);
      g_assert (NULL != mydata);

      g_trace ("pgmSourceTable_free_loop_context (my_loop_context:%p mydata:%p)",
            (gpointer)my_loop_context, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context;
      g_free (context);
      my_loop_context = NULL;

      g_static_rw_lock_reader_unlock (&pgm_transport_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 */
      g_assert (NULL != handler);
      g_assert (NULL != reginfo);
      g_assert (NULL != reqinfo);
      g_assert (NULL != requests);

      g_trace ("pgmSourceTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)",
            (gpointer)handler, (gpointer)reginfo, (gpointer)reqinfo, (gpointer)requests);
      
      switch (reqinfo->mode)
      {

/* Read-support (also covers GetNext requests) */

      case MODE_GET:
            for (netsnmp_request_info* request=requests; request; request=request->next)
            {
                  pgm_transport_t* transport = (pgm_transport_t*)netsnmp_extract_iterator_context(request);

                  if (transport == 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, "pgmSourceTable_handler: empty table request info.\n");
                        continue;
                  }

                  switch (table_info->colnum)
                  {
                  case COLUMN_PGMSOURCESOURCEADDRESS: {
                        struct sockaddr_in s4;
                        if (AF_INET == transport->send_gsr.gsr_source.ss_family)
                              memcpy (&s4, &transport->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 == transport->send_gsr.gsr_group.ss_family)
                              memcpy (&s4, &transport->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:
                        {
                        unsigned dport = g_ntohs (transport->dport);
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&dport, sizeof(dport) );
                        }
                        break;

                  case COLUMN_PGMSOURCESOURCEGSI:
/* copy index[0] */
                        snmp_set_var_typed_value(     var, ASN_OCTET_STR,
                                                (u_char*)table_info->indexes->val.string,
                                                table_info->indexes->val_len);
                        break;

                  case COLUMN_PGMSOURCESOURCEPORTNUMBER:
/* copy index[1] */
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (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)
{
      g_trace ("initialize_table_pgmSourceConfigTable ()");

      static 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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmSourceConfigTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      g_static_rw_lock_reader_lock (&pgm_transport_list_lock);

      if (pgm_transport_list == NULL) {
            g_static_rw_lock_reader_unlock (&pgm_transport_list_lock);
            return NULL;
      }

/* create our own context for this SNMP loop */
      pgm_snmp_context_t* context = g_malloc0 (sizeof(pgm_snmp_context_t));
      context->list = pgm_transport_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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmSourceConfigTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context;
      netsnmp_variable_list *idx = put_index_data;

      if ( context->list == NULL )
      {
            return NULL;
      }

      pgm_transport_t* transport = context->list->data;

/* pgmSourceGlobalId */
      char gsi[sizeof("000" "000" "000" "000" "000" "000")];
      snprintf(gsi, sizeof(gsi), "%hhu%hhu%hhu%hhu%hhu%hhu",
            transport->tsi.gsi.identifier[0],
            transport->tsi.gsi.identifier[1],
            transport->tsi.gsi.identifier[2],
            transport->tsi.gsi.identifier[3],
            transport->tsi.gsi.identifier[4],
            transport->tsi.gsi.identifier[5]);
      snmp_set_var_typed_value( idx, ASN_OCTET_STR, (u_char*)&gsi, strlen(gsi) );
      idx = idx->next_variable;

/* pgmSourceSourcePort */
      unsigned sport = g_ntohs (transport->tsi.sport);
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (u_char*)&sport, sizeof(sport) );

      *my_data_context = transport;
      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 */
        g_assert (NULL != my_loop_context);
      g_assert (NULL != mydata);

        g_trace ("pgmSourceConfigTable_free_loop_context (my_loop_context:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context;
      g_free(context);
      my_loop_context = NULL;

      g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != handler);
        g_assert (NULL != reginfo);
        g_assert (NULL != reqinfo);
        g_assert (NULL != requests);

        g_trace ("pgmSourceConfigTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)",
                (gpointer)handler, (gpointer)reginfo, (gpointer)reqinfo, (gpointer)requests);

      switch (reqinfo->mode)
      {

/* Read-support (also covers GetNext requests) */

      case MODE_GET:
            for (netsnmp_request_info* request=requests; request; request=request->next)
            {
                  pgm_transport_t* transport = (pgm_transport_t*)netsnmp_extract_iterator_context(request);

                  if (transport == 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, "pgmSourceTable_handler: empty table request info.\n");
                        continue;
                  }

                  switch (table_info->colnum)
                  {
                  case COLUMN_PGMSOURCETTL:
                        {
                        unsigned hops = transport->hops;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&hops, sizeof(hops) );
                        }
                        break;

/* FIXED: pgmSourceAdvMode = data(1) */
                  case COLUMN_PGMSOURCEADVMODE:
                        {
                        unsigned adv_mode = PGMSOURCEADVMODE_DATA;
                        snmp_set_var_typed_value(     var, ASN_INTEGER,
                                                (u_char*)&adv_mode, sizeof(adv_mode) );
                        }
                        break;

/* FIXED: pgmSourceLateJoin = disable(2) */
                  case COLUMN_PGMSOURCELATEJOIN:
                        {
                        unsigned late_join = PGMSOURCELATEJOIN_DISABLE;
                        snmp_set_var_typed_value(     var, ASN_INTEGER,
                                                (u_char*)&late_join, sizeof(late_join) );
                        }
                        break;

                  case COLUMN_PGMSOURCETXWMAXRTE:
                        {
                        unsigned txw_max_rte = transport->txw_max_rte;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&txw_max_rte, sizeof(txw_max_rte) );
                        }
                        break;

                  case COLUMN_PGMSOURCETXWSECS:
                        {
                        unsigned txw_secs = transport->txw_secs;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&txw_secs, sizeof(txw_secs) );
                        }
                        break;

/* FIXED: TXW_ADV_SECS = 0 */
                  case COLUMN_PGMSOURCETXWADVSECS:
                        {
                        unsigned txw_adv_secs = 0;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&txw_adv_secs, sizeof(txw_adv_secs) );
                        }
                        break;

/* FIXED: pgmSourceAdvIvl = TXW_ADV_SECS * 1000 = 0 */
                  case COLUMN_PGMSOURCEADVIVL:
                        {
                        unsigned adv_ivl = 0;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&adv_ivl, sizeof(adv_ivl) );
                        }
                        break;

                  case COLUMN_PGMSOURCESPMIVL:
                        {
                        unsigned spm_ivl = pgm_to_msecs(transport->spm_ambient_interval);
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&spm_ivl, sizeof(spm_ivl) );
                        }
                        break;

/* TODO: IHB_MIN */
                  case COLUMN_PGMSOURCESPMHEARTBEATIVLMIN:
                        {
                        unsigned ihb_min = 0;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&ihb_min, sizeof(ihb_min) );
                        }
                        break;

/* TODO: IHB_MAX */
                  case COLUMN_PGMSOURCESPMHEARTBEATIVLMAX:
                        {
                        unsigned ihb_max = 0;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&ihb_max, sizeof(ihb_max) );
                        }
                        break;

/* NAK_BO_IVL */
                  case COLUMN_PGMSOURCERDATABACKOFFIVL:
                        {
                        unsigned nak_bo_ivl = pgm_to_msecs(transport->nak_bo_ivl);
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&nak_bo_ivl, sizeof(nak_bo_ivl) );
                        }
                        break;

/* FIXED: pgmSourceFEC = disabled(1) */
                  case COLUMN_PGMSOURCEFEC:
                        {
                        unsigned fec = PGMSOURCEADVMODE_DATA;
                        snmp_set_var_typed_value(     var, ASN_INTEGER,
                                                (u_char*)&fec, sizeof(fec) );
                        }
                        break;

/* FIXED: pgmSourceFECTransmissionGrpSize = 0 */
                  case COLUMN_PGMSOURCEFECTRANSMISSIONGRPSIZE:
                        {
                        unsigned fec_tgs = 0;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&fec_tgs, sizeof(fec_tgs) );
                        }
                        break;

/* FIXED: pgmSourceFECProactiveParitySize = 0 */
                  case COLUMN_PGMSOURCEFECPROACTIVEPARITYSIZE:
                        {
                        unsigned fec_paps = 0;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&fec_paps, sizeof(fec_paps) );
                        }
                        break;

                  case COLUMN_PGMSOURCESPMPATHADDRESS: {
                        struct sockaddr_in s4;
                        if (AF_INET == transport->recv_gsr[0].gsr_source.ss_family)
                              memcpy (&s4, &transport->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)
{
      g_trace ("initialize_table_pgmSourcePerformanceTable ()");

      static 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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmSourcePerformanceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      g_static_rw_lock_reader_lock (&pgm_transport_list_lock);

      if (pgm_transport_list == NULL) {
            g_static_rw_lock_reader_unlock (&pgm_transport_list_lock);
            return NULL;
      }

/* create our own context for this SNMP loop */
      pgm_snmp_context_t* context = g_malloc0 (sizeof(pgm_snmp_context_t));
      context->list = pgm_transport_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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmSourcePerformanceTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context;
      netsnmp_variable_list *idx = put_index_data;

      if ( context->list == NULL )
      {
            return NULL;
      }

      pgm_transport_t* transport = context->list->data;

/* pgmSourceGlobalId */
      char gsi[sizeof("000" "000" "000" "000" "000" "000")];
      snprintf(gsi, sizeof(gsi), "%hhu%hhu%hhu%hhu%hhu%hhu",
            transport->tsi.gsi.identifier[0],
            transport->tsi.gsi.identifier[1],
            transport->tsi.gsi.identifier[2],
            transport->tsi.gsi.identifier[3],
            transport->tsi.gsi.identifier[4],
            transport->tsi.gsi.identifier[5]);
      snmp_set_var_typed_value( idx, ASN_OCTET_STR, (u_char*)&gsi, strlen(gsi) );
      idx = idx->next_variable;

/* pgmSourceSourcePort */
      unsigned sport = g_ntohs (transport->tsi.sport);
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (u_char*)&sport, sizeof(sport) );

      *my_data_context = transport;
      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 */
        g_assert (NULL != my_loop_context);
      g_assert (NULL != mydata);

        g_trace ("pgmPerformanceSourceTable_free_loop_context (my_loop_context:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)mydata);
 
      pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context;
      g_free(context);
      my_loop_context = NULL;

      g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != handler);
        g_assert (NULL != reginfo);
        g_assert (NULL != reqinfo);
        g_assert (NULL != requests);

        g_trace ("pgmSourcePerformanceTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)",
                (gpointer)handler, (gpointer)reginfo, (gpointer)reqinfo, (gpointer)requests);

      switch (reqinfo->mode)
      {

/* Read-support (also covers GetNext requests) */

      case MODE_GET:
            for (netsnmp_request_info* request=requests; request; request=request->next)
            {
                  pgm_transport_t* transport = (pgm_transport_t*)netsnmp_extract_iterator_context(request);

                  if (transport == 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, "pgmSourceTable_handler: empty table request info.\n");
                        continue;
                  }

                  switch (table_info->colnum)
                  {
                  case COLUMN_PGMSOURCEDATABYTESSENT:
                        {
                        unsigned data_bytes = transport->cumulative_stats[PGM_PC_SOURCE_DATA_BYTES_SENT];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&data_bytes, sizeof(data_bytes) );
                        }
                        break;

                  case COLUMN_PGMSOURCEDATAMSGSSENT:
                        {
                        unsigned data_msgs = transport->cumulative_stats[PGM_PC_SOURCE_DATA_MSGS_SENT];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&data_msgs, sizeof(data_msgs) );
                        }
                        break;

                  case COLUMN_PGMSOURCEBYTESBUFFERED:
                        {
                        pgm_txw_t* window = (pgm_txw_t*)transport->window;
                        unsigned bytes_buffered = transport->can_send_data ? pgm_txw_size (window) : 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&bytes_buffered, sizeof(bytes_buffered) );
                        }
                        break;

                  case COLUMN_PGMSOURCEMSGSBUFFERED:
                        {
                        pgm_txw_t* window = (pgm_txw_t*)transport->window;
                        unsigned msgs_buffered = transport->can_send_data ? pgm_txw_length (window) : 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&msgs_buffered, sizeof(msgs_buffered) );
                        }
                        break;

/* PGM_PC_SOURCE_SELECTIVE_BYTES_RETRANSMITTED + COLUMN_PGMSOURCEPARITYBYTESRETRANSMITTED */
                  case COLUMN_PGMSOURCEBYTESRETRANSMITTED:
                        {
                        unsigned bytes_resent = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_BYTES_RETRANSMITTED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&bytes_resent, sizeof(bytes_resent) );
                        }
                        break;

/* PGM_PC_SOURCE_SELECTIVE_MSGS_RETRANSMITTED + COLUMN_PGMSOURCEPARITYMSGSRETRANSMITTED */
                  case COLUMN_PGMSOURCEMSGSRETRANSMITTED:
                        {
                        unsigned msgs_resent = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_MSGS_RETRANSMITTED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&msgs_resent, sizeof(msgs_resent) );
                        }
                        break;

                  case COLUMN_PGMSOURCEBYTESSENT:
                        {
                        unsigned bytes_sent = transport->cumulative_stats[PGM_PC_SOURCE_BYTES_SENT];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&bytes_sent, sizeof(bytes_sent) );
                        }
                        break;

/* COLUMN_PGMSOURCEPARITYNAKPACKETSRECEIVED + COLUMN_PGMSOURCESELECTIVENAKPACKETSRECEIVED */
                  case COLUMN_PGMSOURCERAWNAKSRECEIVED:
                        {
                        unsigned nak_packets = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&nak_packets, sizeof(nak_packets) );
                        }
                        break;

/* PGM_PC_SOURCE_SELECTIVE_NAKS_IGNORED + COLUMN_PGMSOURCEPARITYNAKSIGNORED */
                  case COLUMN_PGMSOURCENAKSIGNORED:
                        {
                        unsigned naks_ignored = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_IGNORED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_ignored, sizeof(naks_ignored) );
                        }
                        break;

                  case COLUMN_PGMSOURCECKSUMERRORS:
                        {
                        unsigned cksum_errors = transport->cumulative_stats[PGM_PC_SOURCE_CKSUM_ERRORS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&cksum_errors, sizeof(cksum_errors) );
                        }
                        break;

                  case COLUMN_PGMSOURCEMALFORMEDNAKS:
                        {
                        unsigned malformed_naks = transport->cumulative_stats[PGM_PC_SOURCE_MALFORMED_NAKS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&malformed_naks, sizeof(malformed_naks) );
                        }
                        break;

                  case COLUMN_PGMSOURCEPACKETSDISCARDED:
                        {
                        unsigned packets_discarded = transport->cumulative_stats[PGM_PC_SOURCE_PACKETS_DISCARDED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&packets_discarded, sizeof(packets_discarded) );
                        }
                        break;

/* PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED + COLUMN_PGMSOURCEPARITYNAKSRECEIVED */
                  case COLUMN_PGMSOURCENAKSRCVD:
                        {
                        unsigned naks_received = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_received, sizeof(naks_received) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEPARITYBYTESRETRANSMITTED:
                        {
                        unsigned parity_bytes_resent = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_bytes_resent, sizeof(parity_bytes_resent) );
                        }
                        break;

                  case COLUMN_PGMSOURCESELECTIVEBYTESRETRANSMITED:
                        {
                        unsigned selective_bytes_resent = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_BYTES_RETRANSMITTED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&selective_bytes_resent, sizeof(selective_bytes_resent) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEPARITYMSGSRETRANSMITTED:
                        {
                        unsigned parity_msgs_resent = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_msgs_resent, sizeof(parity_msgs_resent) );
                        }
                        break;

                  case COLUMN_PGMSOURCESELECTIVEMSGSRETRANSMITTED:
                        {
                        unsigned selective_msgs_resent = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_MSGS_RETRANSMITTED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&selective_msgs_resent, sizeof(selective_msgs_resent) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEBYTESADMIT:
                        {
                        unsigned bytes_admit = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&bytes_admit, sizeof(bytes_admit) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEMSGSADMIT:
                        {
                        unsigned msgs_admit = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&msgs_admit, sizeof(msgs_admit) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEPARITYNAKPACKETSRECEIVED:
                        {
                        unsigned parity_nak_packets = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_nak_packets, sizeof(parity_nak_packets) );
                        }
                        break;

                  case COLUMN_PGMSOURCESELECTIVENAKPACKETSRECEIVED:
                        {
                        unsigned selective_nak_packets = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&selective_nak_packets, sizeof(selective_nak_packets) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEPARITYNAKSRECEIVED:
                        {
                        unsigned parity_naks = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_naks, sizeof(parity_naks) );
                        }
                        break;

                  case COLUMN_PGMSOURCESELECTIVENAKSRECEIVED:
                        {
                        unsigned selective_naks = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&selective_naks, sizeof(selective_naks) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEPARITYNAKSIGNORED:
                        {
                        unsigned parity_naks_ignored = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_naks_ignored, sizeof(parity_naks_ignored) );
                        }
                        break;

                  case COLUMN_PGMSOURCESELECTIVENAKSIGNORED:
                        {
                        unsigned selective_naks_ignored = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NAKS_IGNORED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&selective_naks_ignored, sizeof(selective_naks_ignored) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEACKERRORS:
                        {
                        unsigned ack_errors = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&ack_errors, sizeof(ack_errors) );
                        }
                        break;

                  case COLUMN_PGMSOURCEPGMCCACKER:
                        snmp_set_var_typed_value(     var, ASN_IPADDRESS,
                                                (u_char*)0,
                                                0);
                        break;

                  case COLUMN_PGMSOURCETRANSMISSIONCURRENTRATE:
                        {
                        unsigned tx_current_rate = transport->cumulative_stats[PGM_PC_SOURCE_TRANSMISSION_CURRENT_RATE];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&tx_current_rate, sizeof(tx_current_rate) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEACKPACKETSRECEIVED:
                        {
                        unsigned ack_packets = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&ack_packets, sizeof(ack_packets) );
                        }
                        break;

/* COLUMN_PGMSOURCEPARITYNNAKPACKETSRECEIVED + COLUMN_PGMSOURCESELECTIVENNAKPACKETSRECEIVED */
                  case COLUMN_PGMSOURCENNAKPACKETSRECEIVED:
                        {
                        unsigned nnak_packets = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAK_PACKETS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&nnak_packets, sizeof(nnak_packets) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEPARITYNNAKPACKETSRECEIVED:
                        {
                        unsigned parity_nnak_packets = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_nnak_packets, sizeof(parity_nnak_packets) );
                        }
                        break;

                  case COLUMN_PGMSOURCESELECTIVENNAKPACKETSRECEIVED:
                        {
                        unsigned selective_nnak_packets = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAK_PACKETS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&selective_nnak_packets, sizeof(selective_nnak_packets) );
                        }
                        break;

/* COLUMN_PGMSOURCEPARITYNNAKSRECEIVED + COLUMN_PGMSOURCESELECTIVENNAKSRECEIVED */
                  case COLUMN_PGMSOURCENNAKSRECEIVED:
                        {
                        unsigned nnaks_received = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAKS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&nnaks_received, sizeof(nnaks_received) );
                        }
                        break;

/* FIXED: 0 */
                  case COLUMN_PGMSOURCEPARITYNNAKSRECEIVED:
                        {
                        unsigned parity_nnaks = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_nnaks, sizeof(parity_nnaks) );
                        }
                        break;

                  case COLUMN_PGMSOURCESELECTIVENNAKSRECEIVED:
                        {
                        unsigned selective_nnaks = transport->cumulative_stats[PGM_PC_SOURCE_SELECTIVE_NNAKS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&selective_nnaks, sizeof(selective_nnaks) );
                        }
                        break;

                  case COLUMN_PGMSOURCENNAKERRORS:
                        {
                        unsigned malformed_nnaks = transport->cumulative_stats[PGM_PC_SOURCE_NNAK_ERRORS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (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)
{
      g_trace ("initialize_table_pgmReceiverTable ()");

      static 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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      g_static_rw_lock_reader_lock (&pgm_transport_list_lock);

      if (pgm_transport_list == NULL) {
            g_static_rw_lock_reader_unlock (&pgm_transport_list_lock);
            return NULL;
      }

/* create our own context for this SNMP loop */
      pgm_snmp_context_t* context = g_malloc0 (sizeof(pgm_snmp_context_t));

/* hunt to find first node, through all transports */
      for (context->list = pgm_transport_list; context->list; context->list = context->list->next)
      {
/* and through all peers for each transport */
            pgm_transport_t* transport = (pgm_transport_t*)context->list->data;
            g_static_rw_lock_reader_lock (&transport->peers_lock);
            context->node = transport->peers_list;
            if (context->node) {
/* maintain this transport's peers lock */
                  break;
            }

            g_static_rw_lock_reader_unlock (&transport->peers_lock);
      }

/* no node found */
      if (context->node == NULL) {
            g_free( context );
            g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverTable_get_next_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context;
      netsnmp_variable_list *idx = put_index_data;

      if ( context->list == NULL )
      {
            return NULL;
      }

      pgm_transport_t* transport = context->list->data;

      if ( context->node == NULL )
      {
            return NULL;
      }

      pgm_peer_t* peer = context->node->data;

/* pgmReceiverGlobalId */
      char gsi[sizeof("000" "000" "000" "000" "000" "000")];
      snprintf(gsi, sizeof(gsi), "%hhu%hhu%hhu%hhu%hhu%hhu",
            peer->tsi.gsi.identifier[0],
            peer->tsi.gsi.identifier[1],
            peer->tsi.gsi.identifier[2],
            peer->tsi.gsi.identifier[3],
            peer->tsi.gsi.identifier[4],
            peer->tsi.gsi.identifier[5]);
      snmp_set_var_typed_value( idx, ASN_OCTET_STR, (u_char*)&gsi, strlen(gsi) );
      idx = idx->next_variable;

/* pgmReceiverSourcePort */
      unsigned sport = g_ntohs (peer->tsi.sport);
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (u_char*)&sport, sizeof(sport) );
      idx = idx->next_variable;

/* pgmReceiverInstance */
      unsigned instance = context->instance++;
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (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)
            {
                  g_static_rw_lock_reader_unlock (&transport->peers_lock);
                  context->list = context->list->next;
                  transport = context->list->data;
                  g_static_rw_lock_reader_lock (&transport->peers_lock);
                  context->node = transport->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 */
        g_assert (NULL != my_loop_context);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverTable_free_loop_context (my_loop_context:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context;

/* check for intra-peer state */
      if (context->list) {
            pgm_transport_t* transport = context->list->data;
            g_static_rw_lock_reader_unlock (&transport->peers_lock);
      }

      g_free(context);
      my_loop_context = NULL;

      g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != handler);
        g_assert (NULL != reginfo);
        g_assert (NULL != reqinfo);
        g_assert (NULL != requests);

        g_trace ("pgmReceiverTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)",
                (gpointer)handler, (gpointer)reginfo, (gpointer)reqinfo, (gpointer)requests);

      switch (reqinfo->mode)
      {

/* Read-support (also covers GetNext requests) */

      case MODE_GET:
            for (netsnmp_request_info* request=requests; request; request=request->next)
            {
                  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)
                  {
                  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 transport */
                  case COLUMN_PGMRECEIVERDESTPORT:
                        {
                        unsigned dport = g_ntohs (peer->transport->dport);
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (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;
                  }

                  case COLUMN_PGMRECEIVERSOURCEGSI:
/* copy index[0] */
                        snmp_set_var_typed_value(     var, ASN_OCTET_STR,
                                                (u_char*)table_info->indexes->val.string,
                                                table_info->indexes->val_len);
                        break;

                  case COLUMN_PGMRECEIVERSOURCEPORTNUMBER:
/* copy index[1] */
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)table_info->indexes->next_variable->val.integer,
                                                table_info->indexes->next_variable->val_len);
                        break;

                  case COLUMN_PGMRECEIVERUNIQUEINSTANCE:
/* copy index[2] */
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (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)
{
      g_trace ("initialize_table_pgmReceiverConfigTable ()");

      static 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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverConfigTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      g_static_rw_lock_reader_lock (&pgm_transport_list_lock);

      if (pgm_transport_list == NULL) {
            g_static_rw_lock_reader_unlock (&pgm_transport_list_lock);
            return NULL;
      }

/* create our own context for this SNMP loop */
      pgm_snmp_context_t* context = g_malloc0 (sizeof(pgm_snmp_context_t));

/* hunt to find first node, through all transports */
      for (context->list = pgm_transport_list; context->list; context->list = context->list->next)
      {
/* and through all peers for each transport */
            pgm_transport_t* transport = (pgm_transport_t*)context->list->data;
            g_static_rw_lock_reader_lock (&transport->peers_lock);
            context->node = transport->peers_list;
            if (context->node)
                  break;

            g_static_rw_lock_reader_unlock (&transport->peers_lock);
      }

/* no node found */
      if (context->node == NULL) {
            g_free( context );
            g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverConfigTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context;
      netsnmp_variable_list *idx = put_index_data;

      if ( context->list == NULL )
      {
            return NULL;
      }

      pgm_transport_t* transport = context->list->data;

      if ( context->node == NULL )
      {
            return NULL;
      }

      pgm_peer_t* peer = context->node->data;

/* pgmReceiverGlobalId */
      char gsi[sizeof("000" "000" "000" "000" "000" "000")];
      snprintf(gsi, sizeof(gsi), "%hhu%hhu%hhu%hhu%hhu%hhu",
            peer->tsi.gsi.identifier[0],
            peer->tsi.gsi.identifier[1],
            peer->tsi.gsi.identifier[2],
            peer->tsi.gsi.identifier[3],
            peer->tsi.gsi.identifier[4],
            peer->tsi.gsi.identifier[5]);
      snmp_set_var_typed_value( idx, ASN_OCTET_STR, (u_char*)&gsi, strlen(gsi) );
      idx = idx->next_variable;

/* pgmReceiverSourcePort */
      unsigned sport = g_ntohs (peer->tsi.sport);
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (u_char*)&sport, sizeof(sport) );
      idx = idx->next_variable;

/* pgmReceiverInstance */
      unsigned instance = context->instance++;
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (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)
            {
                  g_static_rw_lock_reader_unlock (&transport->peers_lock);
                  context->list = context->list->next;
                  transport = context->list->data;
                  g_static_rw_lock_reader_lock (&transport->peers_lock);
                  context->node = transport->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 */
        g_assert (NULL != my_loop_context);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverConfigTable_free_loop_context (my_loop_context:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context;

/* check for intra-peer state */
      if (context->list) {
            pgm_transport_t* transport = context->list->data;
            g_static_rw_lock_reader_unlock (&transport->peers_lock);
      }

      g_free(context);
      my_loop_context = NULL;

      g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != handler);
        g_assert (NULL != reginfo);
        g_assert (NULL != reqinfo);
        g_assert (NULL != requests);

        g_trace ("pgmReceiverConfigTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)",
                (gpointer)handler, (gpointer)reginfo, (gpointer)reqinfo, (gpointer)requests);

      switch (reqinfo->mode)
      {

/* Read-support (also covers GetNext requests) */

      case MODE_GET:
            for (netsnmp_request_info* request=requests; request; request=request->next)
            {
                  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 transport */
                  case COLUMN_PGMRECEIVERNAKBACKOFFIVL:
                        {
                        unsigned nak_bo_ivl = peer->transport->nak_bo_ivl;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&nak_bo_ivl, sizeof(nak_bo_ivl) );
                        }
                        break;

/* nak_rpt_ivl from transport */
                  case COLUMN_PGMRECEIVERNAKREPEATIVL:
                        {
                        unsigned nak_rpt_ivl = peer->transport->nak_rpt_ivl;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&nak_rpt_ivl, sizeof(nak_rpt_ivl) );
                        }
                        break;

/* nak_ncf_retries from transport */
                  case COLUMN_PGMRECEIVERNAKNCFRETRIES:
                        {
                        unsigned nak_ncf_retries = peer->transport->nak_ncf_retries;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&nak_ncf_retries, sizeof(nak_ncf_retries) );
                        }
                        break;

/* nak_rdata_ivl from transport */
                  case COLUMN_PGMRECEIVERNAKRDATAIVL:
                        {
                        unsigned nak_rdata_ivl = peer->transport->nak_rdata_ivl;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&nak_rdata_ivl, sizeof(nak_rdata_ivl) );
                        }
                        break;

/* nak_data_retries from transport */
                  case COLUMN_PGMRECEIVERNAKDATARETRIES:
                        {
                        unsigned nak_data_retries = peer->transport->nak_data_retries;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&nak_data_retries, sizeof(nak_data_retries) );
                        }
                        break;

/* FIXED: pgmReceiverSendNaks = enabled(1) */
                  case COLUMN_PGMRECEIVERSENDNAKS:
                        {
                        unsigned send_naks = PGMRECEIVERSENDNAKS_ENABLED;
                        snmp_set_var_typed_value(     var, ASN_INTEGER,
                                                (u_char*)&send_naks, sizeof(send_naks) );
                        }
                        break;

/* FIXED: pgmReceiverLateJoin = disabled(2) */
                  case COLUMN_PGMRECEIVERLATEJOIN:
                        {
                        unsigned late_join = PGMRECEIVERLATEJOIN_DISABLED;
                        snmp_set_var_typed_value(     var, ASN_INTEGER,
                                                (u_char*)&late_join, sizeof(late_join) );
                        }
                        break;

/* FIXED: 1 for multicast */
                  case COLUMN_PGMRECEIVERNAKTTL:
                        {
                        unsigned nak_hops = 1;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (u_char*)&nak_hops, sizeof(nak_hops) );
                        }
                        break;

/* FIXED: pgmReceiverDeliveryOrder = ordered(2) */
                  case COLUMN_PGMRECEIVERDELIVERYORDER:
                        {
                        unsigned delivery_order = PGMRECEIVERDELIVERYORDER_ORDERED;
                        snmp_set_var_typed_value(     var, ASN_INTEGER,
                                                (u_char*)&delivery_order, sizeof(delivery_order) );
                        }
                        break;

/* FIXED: pgmReceiverMcastNaks = disabled(2) */
                  case COLUMN_PGMRECEIVERMCASTNAKS:
                        {
                        unsigned mcast_naks = PGMRECEIVERMCASTNAKS_DISABLED;
                        snmp_set_var_typed_value(     var, ASN_INTEGER,
                                                (u_char*)&mcast_naks, sizeof(mcast_naks) );
                        }
                        break;

/* TODO: traps */
                  case COLUMN_PGMRECEIVERNAKFAILURETHRESHOLDTIMER:
                  case COLUMN_PGMRECEIVERNAKFAILURETHRESHOLD:
                        {
                        unsigned threshold = 0;
                        snmp_set_var_typed_value(     var, ASN_UNSIGNED,
                                                (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)
{
      g_trace ("initialize_table_pgmReceiverPerformanceTable ()");

      static 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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverPerformanceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      g_static_rw_lock_reader_lock (&pgm_transport_list_lock);

      if (pgm_transport_list == NULL) {
            g_static_rw_lock_reader_unlock (&pgm_transport_list_lock);
            return NULL;
      }

/* create our own context for this SNMP loop */
      pgm_snmp_context_t* context = g_malloc0 (sizeof(pgm_snmp_context_t));

/* hunt to find first node, through all transports */
      for (context->list = pgm_transport_list; context->list; context->list = context->list->next)
      {
/* and through all peers for each transport */
            pgm_transport_t* transport = (pgm_transport_t*)context->list->data;
            g_static_rw_lock_reader_lock (&transport->peers_lock);
            context->node = transport->peers_list;
            if (context->node)
                  break;

            g_static_rw_lock_reader_unlock (&transport->peers_lock);
      }

/* no node found */
      if (context->node == NULL) {
            g_free( context );
            g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != my_loop_context);
        g_assert (NULL != my_data_context);
        g_assert (NULL != put_index_data);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverPerformanceTable_get_first_data_point (my_loop_context:%p my_data_context:%p put_index_data:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)my_data_context, (gpointer)put_index_data, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)*my_loop_context;
      netsnmp_variable_list *idx = put_index_data;

      if ( context->list == NULL )
      {
            return NULL;
      }

      pgm_transport_t* transport = context->list->data;

      if ( context->node == NULL )
      {
            return NULL;
      }

      pgm_peer_t* peer = context->node->data;

/* pgmReceiverGlobalId */
      char gsi[sizeof("000" "000" "000" "000" "000" "000")];
      snprintf(gsi, sizeof(gsi), "%hhu%hhu%hhu%hhu%hhu%hhu",
            peer->tsi.gsi.identifier[0],
            peer->tsi.gsi.identifier[1],
            peer->tsi.gsi.identifier[2],
            peer->tsi.gsi.identifier[3],
            peer->tsi.gsi.identifier[4],
            peer->tsi.gsi.identifier[5]);
      snmp_set_var_typed_value( idx, ASN_OCTET_STR, (u_char*)&gsi, strlen(gsi) );
      idx = idx->next_variable;

/* pgmReceiverSourcePort */
      unsigned sport = g_ntohs (peer->tsi.sport);
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (u_char*)&sport, sizeof(sport) );
      idx = idx->next_variable;

/* pgmReceiverInstance */
      unsigned instance = context->instance++;
      snmp_set_var_typed_value( idx, ASN_UNSIGNED, (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)
            {
                  g_static_rw_lock_reader_unlock (&transport->peers_lock);
                  context->list = context->list->next;
                  transport = context->list->data;
                  g_static_rw_lock_reader_lock (&transport->peers_lock);
                  context->node = transport->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 */
        g_assert (NULL != my_loop_context);
      g_assert (NULL != mydata);

        g_trace ("pgmReceiverPerformanceTable_free_loop_context (my_loop_context:%p mydata:%p)",
                (gpointer)my_loop_context, (gpointer)mydata);

      pgm_snmp_context_t* context = (pgm_snmp_context_t*)my_loop_context;

/* check for intra-peer state */
      if (context->list) {
            pgm_transport_t* transport = context->list->data;
            g_static_rw_lock_reader_unlock (&transport->peers_lock);
      }

      g_free(context);
      my_loop_context = NULL;

      g_static_rw_lock_reader_unlock (&pgm_transport_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 */
        g_assert (NULL != handler);
        g_assert (NULL != reginfo);
        g_assert (NULL != reqinfo);
        g_assert (NULL != requests);

        g_trace ("pgmReceiverPerformanceTable_handler (handler:%p reginfo:%p reqinfo:%p requests:%p)",
                (gpointer)handler, (gpointer)reginfo, (gpointer)reqinfo, (gpointer)requests);

      switch (reqinfo->mode)
      {

/* Read-support (also covers GetNext requests) */

      case MODE_GET:
            for (netsnmp_request_info* request=requests; request; request=request->next)
            {
                  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)
                  {
                  case COLUMN_PGMRECEIVERDATABYTESRECEIVED:
                        {
                        unsigned data_bytes = peer->cumulative_stats[PGM_PC_RECEIVER_DATA_BYTES_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&data_bytes, sizeof(data_bytes) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERDATAMSGSRECEIVED:
                        {
                        unsigned data_msgs = peer->cumulative_stats[PGM_PC_RECEIVER_DATA_MSGS_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&data_msgs, sizeof(data_msgs) );
                        }
                        break;

/* total */
                  case COLUMN_PGMRECEIVERNAKSSENT:
                        {
                        unsigned naks_sent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SENT];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_sent, sizeof(naks_sent) );
                        }
                        break;
      
/* total */ 
                  case COLUMN_PGMRECEIVERNAKSRETRANSMITTED:
                        {
                        unsigned naks_resent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_RETRANSMITTED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_resent, sizeof(naks_resent) );
                        }
                        break;
      
/* total */ 
                  case COLUMN_PGMRECEIVERNAKFAILURES:
                        {
                        unsigned nak_failures = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_FAILED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&nak_failures, sizeof(nak_failures) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERBYTESRECEIVED:
                        {
                        unsigned bytes_received = peer->cumulative_stats[PGM_PC_RECEIVER_BYTES_RECEIVED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&bytes_received, sizeof(bytes_received) );
                        }
                        break;
      
/* total */ 
                  case COLUMN_PGMRECEIVERNAKSSUPPRESSED:
                        {
                        unsigned naks_suppressed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SUPPRESSED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_suppressed, sizeof(naks_suppressed) );
                        }
                        break;
      
/* bogus: same as source checksum errors */     
                  case COLUMN_PGMRECEIVERCKSUMERRORS:
                        {
                        unsigned cksum_errors = peer->transport->cumulative_stats[PGM_PC_SOURCE_CKSUM_ERRORS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&cksum_errors, sizeof(cksum_errors) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERMALFORMEDSPMS:
                        {
                        unsigned malformed_spms = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_SPMS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&malformed_spms, sizeof(malformed_spms) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERMALFORMEDODATA:
                        {
                        unsigned malformed_odata = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_ODATA];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&malformed_odata, sizeof(malformed_odata) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERMALFORMEDRDATA:
                        {
                        unsigned malformed_rdata = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_RDATA];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&malformed_rdata, sizeof(malformed_rdata) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERMALFORMEDNCFS:
                        {
                        unsigned malformed_ncfs = peer->cumulative_stats[PGM_PC_RECEIVER_MALFORMED_NCFS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&malformed_ncfs, sizeof(malformed_ncfs) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERPACKETSDISCARDED:
                        {
                        unsigned packets_discarded = peer->cumulative_stats[PGM_PC_RECEIVER_PACKETS_DISCARDED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&packets_discarded, sizeof(packets_discarded) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERLOSSES:
                        {
                        unsigned losses = ((pgm_rxw_t*)peer->window)->cumulative_losses;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&losses, sizeof(losses) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERBYTESDELIVEREDTOAPP:
                        {
                        unsigned bytes_delivered = ((pgm_rxw_t*)peer->window)->bytes_delivered;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&bytes_delivered, sizeof(bytes_delivered) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERMSGSDELIVEREDTOAPP:
                        {
                        unsigned msgs_delivered = ((pgm_rxw_t*)peer->window)->msgs_delivered;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&msgs_delivered, sizeof(msgs_delivered) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERDUPSPMS:
                        {
                        unsigned dup_spms = peer->cumulative_stats[PGM_PC_RECEIVER_DUP_SPMS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&dup_spms, sizeof(dup_spms) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERDUPDATAS:
                        {
                        unsigned dup_data = peer->cumulative_stats[PGM_PC_RECEIVER_DUP_DATAS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&dup_data, sizeof(dup_data) );
                        }
                        break;
      
/* FIXED: 0 */    
                  case COLUMN_PGMRECEIVERDUPPARITIES:
                        {
                        unsigned dup_parity = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&dup_parity, sizeof(dup_parity) );
                        }
                        break;
      
/* COLUMN_PGMRECEIVERPARITYNAKPACKETSSENT + COLUMN_PGMRECEIVERSELECTIVENAKPACKETSSENT */  
                  case COLUMN_PGMRECEIVERNAKPACKETSSENT:
                        {
                        unsigned nak_packets = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAK_PACKETS_SENT];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&nak_packets, sizeof(nak_packets) );
                        }
                        break;
      
/* FIXED: 0 */    
                  case COLUMN_PGMRECEIVERPARITYNAKPACKETSSENT:
                        {
                        unsigned parity_naks = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_naks, sizeof(parity_naks) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERSELECTIVENAKPACKETSSENT:
                        {
                        unsigned nak_packets = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAK_PACKETS_SENT];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&nak_packets, sizeof(nak_packets) );
                        }
                        break;
      
/* FIXED: 0 */    
                  case COLUMN_PGMRECEIVERPARITYNAKSSENT:
                        {
                        unsigned parity_naks = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_naks, sizeof(parity_naks) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERSELECTIVENAKSSENT:
                        {
                        unsigned naks_sent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SENT];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_sent, sizeof(naks_sent) );
                        }
                        break;
      
/* FIXED: 0 */    
                  case COLUMN_PGMRECEIVERPARITYNAKSRETRANSMITTED:
                        {
                        unsigned parity_resent = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_resent, sizeof(parity_resent) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERSELECTIVENAKSRETRANSMITTED:
                        {
                        unsigned naks_resent = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_RETRANSMITTED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_resent, sizeof(naks_resent) );
                        }
                        break;
      
/* COLUMN_PGMRECEIVERPARITYNAKSFAILED + COLUMN_PGMRECEIVERSELECTIVENAKSFAILED */    
                  case COLUMN_PGMRECEIVERNAKSFAILED:
                        {
                        unsigned naks_failed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_FAILED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_failed, sizeof(naks_failed) );
                        }
                        break;
      
/* FIXED: 0 */    
                  case COLUMN_PGMRECEIVERPARITYNAKSFAILED:
                        {
                        unsigned parity_failed = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&parity_failed, sizeof(parity_failed) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERSELECTIVENAKSFAILED:
                        {
                        unsigned naks_failed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_FAILED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&naks_failed, sizeof(naks_failed) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKSFAILEDRXWADVANCED:
                        {
                        unsigned rxw_failed = peer->cumulative_stats[PGM_PC_RECEIVER_NAKS_FAILED_RXW_ADVANCED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&rxw_failed, sizeof(rxw_failed) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKSFALEDNCFRETRIESEXCEEDED:
                        {
                        unsigned ncf_retries = peer->cumulative_stats[PGM_PC_RECEIVER_NAKS_FAILED_NCF_RETRIES_EXCEEDED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&ncf_retries, sizeof(ncf_retries) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKSFAILEDDATARETRIESEXCEEDED:
                        {
                        unsigned data_retries = peer->cumulative_stats[PGM_PC_RECEIVER_NAKS_FAILED_DATA_RETRIES_EXCEEDED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&data_retries, sizeof(data_retries) );
                        }
                        break;
      
/* FIXED: 0 - absolutely no idea what this means */   
                  case COLUMN_PGMRECEIVERNAKSFAILEDGENEXPIRED:
                        {
                        unsigned happy_pandas = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&happy_pandas, sizeof(happy_pandas) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKFAILURESDELIVERED:
                        {
                        unsigned delivered = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_FAILURES_DELIVERED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&delivered, sizeof(delivered) );
                        }
                        break;
      
/* FIXED: 0 */    
                  case COLUMN_PGMRECEIVERPARITYNAKSSUPPRESSED:
                        {
                        unsigned suppressed = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&suppressed, sizeof(suppressed) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERSELECTIVENAKSSUPPRESSED:
                        {
                        unsigned suppressed = peer->cumulative_stats[PGM_PC_RECEIVER_SELECTIVE_NAKS_SUPPRESSED];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&suppressed, sizeof(suppressed) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKERRORS:
                        {
                        unsigned malformed_naks = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_ERRORS];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&malformed_naks, sizeof(malformed_naks) );
                        }
                        break;
      
/* FIXED: 0 */    
                  case COLUMN_PGMRECEIVEROUTSTANDINGPARITYNAKS:
                        {
                        unsigned outstanding_parity = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&outstanding_parity, sizeof(outstanding_parity) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVEROUTSTANDINGSELECTIVENAKS:
                        {
                        unsigned outstanding_selective = ((pgm_rxw_t*)peer->window)->backoff_queue.length
                                                      + ((pgm_rxw_t*)peer->window)->wait_ncf_queue.length
                                                      + ((pgm_rxw_t*)peer->window)->wait_data_queue.length;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (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 */
                                                (u_char*)&last_activity.uint_value, sizeof(last_activity.uint_value) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKSVCTIMEMIN:
                        {
                        unsigned min_repair_time = ((pgm_rxw_t*)peer->window)->min_fill_time;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&min_repair_time, sizeof(min_repair_time) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKSVCTIMEMEAN:
                        {
                        unsigned mean_repair_time = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_SVC_TIME_MEAN];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&mean_repair_time, sizeof(mean_repair_time) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKSVCTIMEMAX:
                        {
                        unsigned max_repair_time = ((pgm_rxw_t*)peer->window)->max_fill_time;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&max_repair_time, sizeof(max_repair_time) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKFAILTIMEMIN:
                        {
                        unsigned min_fail_time = peer->min_fail_time;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&min_fail_time, sizeof(min_fail_time) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKFAILTIMEMEAN:
                        {
                        unsigned mean_fail_time = peer->cumulative_stats[PGM_PC_RECEIVER_NAK_FAIL_TIME_MEAN];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&mean_fail_time, sizeof(mean_fail_time) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKFAILTIMEMAX:
                        {
                        unsigned max_fail_time = peer->max_fail_time;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&max_fail_time, sizeof(max_fail_time) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKTRANSMITMIN:
                        {
                        unsigned min_transmit_count = ((pgm_rxw_t*)peer->window)->min_nak_transmit_count;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&min_transmit_count, sizeof(min_transmit_count) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKTRANSMITMEAN:
                        {
                        unsigned mean_transmit_count = peer->cumulative_stats[PGM_PC_RECEIVER_TRANSMIT_MEAN];
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&mean_transmit_count, sizeof(mean_transmit_count) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERNAKTRANSMITMAX:
                        {
                        unsigned max_transmit_count = ((pgm_rxw_t*)peer->window)->max_nak_transmit_count;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&max_transmit_count, sizeof(max_transmit_count) );
                        }
                        break;
      
/* FIXED: 0 (PGMCC) */  
                  case COLUMN_PGMRECEIVERACKSSENT:
                        {
                        unsigned acks_sent = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&acks_sent, sizeof(acks_sent) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERRXWTRAIL:
                        {
                        unsigned rxw_trail = ((pgm_rxw_t*)peer->window)->rxw_trail;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&rxw_trail, sizeof(rxw_trail) );
                        }
                        break;
            
                  case COLUMN_PGMRECEIVERRXWLEAD:
                        {
                        unsigned rxw_lead = ((pgm_rxw_t*)peer->window)->lead;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (u_char*)&rxw_lead, sizeof(rxw_lead) );
                        }
                        break;
      
/* TODO: traps */ 
                  case COLUMN_PGMRECEIVERNAKFAILURESLASTINTERVAL:
                  case COLUMN_PGMRECEIVERLASTINTERVALNAKFAILURES:
                        {
                        unsigned failures = 0;
                        snmp_set_var_typed_value(     var, ASN_COUNTER, /* ASN_COUNTER32 */
                                                (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)
{
      g_trace ("send_pgmStart_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      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)
{
      g_trace ("send_pgmStop_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      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)
{
      g_trace ("send_pgmNewSourceTrap_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      oid pgmNewSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,3 };
      oid pgmSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,2,100,2,1,6, /* insert index here */ };
      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)
{
      g_trace ("send_pgmClosedSourceTrap_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      oid pgmClosedSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,4 };
      oid pgmSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,2,100,2,1,6, /* insert index here */ };
      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)
{
      g_trace ("send_pgmNewReceiverTrap_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      oid pgmNewReceiverTrap_oid[] = { 1,3,6,1,3,112,2,0,5 };
      oid pgmReceiverSourceGsi_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,8, /* insert index here */ };
      oid pgmReceiverSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,9, /* insert index here */ };
      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)
{
      g_trace ("send_pgmClosedReceiverTrap_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      oid pgmClosedReceiverTrap_oid[] = { 1,3,6,1,3,112,2,0,6 };
      oid pgmReceiverSourceGsi_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,8, /* insert index here */ };
      oid pgmReceiverSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,9, /* insert index here */ };
      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)
{
      g_trace ("send_pgmNakFailuresTrap_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      oid pgmNakFailuresTrap_oid[] = { 1,3,6,1,3,112,2,0,7 };
      oid pgmReceiverSourceGsi_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,8, /* insert index here */ };
      oid pgmReceiverSourcePortNumber_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,9, /* insert index here */ };
      oid pgmReceiverUniqueInstance_oid[] = { 1,3,6,1,3,112,1,3,100,2,1,10, /* insert index here */ };
      oid pgmReceiverNakFailureThresholdTimer_oid[] = { 1,3,6,1,3,112,1,3,100,3,1,14, /* insert index here */ };
      oid pgmReceiverNakFailureThreshold_oid[] = { 1,3,6,1,3,112,1,3,100,3,1,15, /* insert index here */ };
      oid pgmReceiverNakFailuresLastInterval_oid[] = { 1,3,6,1,3,112,1,3,100,4,1,56, /* insert index here */ };
      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)
{
      g_trace ("send_pgmNewDlrSourceTrap_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      oid pgmNewDlrSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,8 };
      oid pgmDlrSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,4,100,2,1,4, /* insert index here */ };
      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)
{
      g_trace ("send_pgmClosedDlrSourceTrap_trap ()");

      netsnmp_variable_list  *var_list = NULL;
      oid pgmClosedDlrSourceTrap_oid[] = { 1,3,6,1,3,112,2,0,9 };
      oid pgmDlrSourceSourceGsi_oid[] = { 1,3,6,1,3,112,1,4,100,2,1,4, /* insert index here */ };
      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 */

Generated by  Doxygen 1.6.0   Back to index