/*
 *  Host Resources MIB - network device group implementation - hr_network.c
 *
 */

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/data_access/interface.h>
#if HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif

#ifdef hpux11
#include <sys/mib.h>
#include <netinet/mib_kern.h>
#endif

#include "host_res.h"
#include "mibII/interfaces.h"
#include "hr_network.h"


        /*********************
	 *
	 *  Kernel & interface information,
	 *   and internal forward declarations
	 *
	 *********************/

void            Init_HR_Network(void);
int             Get_Next_HR_Network(void);
void            Save_HR_Network_Info(void);

const char     *describe_networkIF(int);
int             network_status(int);
int             network_errors(int);
int             header_hrnet(struct variable *, oid *, size_t *, int,
                             size_t *, WriteMethod **);

#define HRN_MONOTONICALLY_INCREASING

        /*********************
	 *
	 *  Initialisation & common implementation functions
	 *
	 *********************/

#define	HRNET_IFINDEX		1

struct variable4 hrnet_variables[] = {
    {HRNET_IFINDEX, ASN_INTEGER, RONLY, var_hrnet, 2, {1, 1}}
};
oid             hrnet_variables_oid[] = { 1, 3, 6, 1, 2, 1, 25, 3, 4 };


void
init_hr_network(void)
{
    init_device[HRDEV_NETWORK] = Init_HR_Network;
    next_device[HRDEV_NETWORK] = Get_Next_HR_Network;
    save_device[HRDEV_NETWORK] = Save_HR_Network_Info;
#ifdef HRN_MONOTONICALLY_INCREASING
    dev_idx_inc[HRDEV_NETWORK] = 1;
#endif

    device_descr[HRDEV_NETWORK] = describe_networkIF;
    device_status[HRDEV_NETWORK] = network_status;
    device_errors[HRDEV_NETWORK] = network_errors;

    REGISTER_MIB("host/hr_network", hrnet_variables, variable4,
                 hrnet_variables_oid);
}

/*
 * header_hrnet(...
 * Arguments:
 * vp     IN      - pointer to variable entry that points here
 * name    IN/OUT  - IN/name requested, OUT/name found
 * length  IN/OUT  - length of IN/OUT oid's 
 * exact   IN      - TRUE if an exact match was requested
 * var_len OUT     - length of variable or 0 if function returned
 * write_method
 * 
 */

int
header_hrnet(struct variable *vp,
             oid * name,
             size_t * length,
             int exact, size_t * var_len, WriteMethod ** write_method)
{
#define HRNET_ENTRY_NAME_LENGTH	11
    oid             newname[MAX_OID_LEN];
    int             net_idx;
    int             result;
    int             LowIndex = -1;

    DEBUGMSGTL(("host/hr_network", "var_hrnet: "));
    DEBUGMSGOID(("host/hr_network", name, *length));
    DEBUGMSG(("host/hr_network", " %d\n", exact));

    memcpy((char *) newname, (char *) vp->name, vp->namelen * sizeof(oid));
    /*
     * Find "next" net entry 
     */

    Init_HR_Network();
    for (;;) {
        net_idx = Get_Next_HR_Network();
        if (net_idx == -1)
            break;
        newname[HRNET_ENTRY_NAME_LENGTH] = net_idx;
        result = snmp_oid_compare(name, *length, newname, vp->namelen + 1);
        if (exact && (result == 0)) {
            LowIndex = net_idx;
            break;
        }
        if (!exact && (result < 0) &&
            (LowIndex == -1 || net_idx < LowIndex)) {
            LowIndex = net_idx;
#ifdef HRN_MONOTONICALLY_INCREASING
            break;
#endif
        }
    }

    if (LowIndex == -1) {
        DEBUGMSGTL(("host/hr_network", "... index out of range\n"));
        return (MATCH_FAILED);
    }

    newname[HRNET_ENTRY_NAME_LENGTH] = LowIndex;
    memcpy((char *) name, (char *) newname,
           (vp->namelen + 1) * sizeof(oid));
    *length = vp->namelen + 1;
    *write_method = 0;
    *var_len = sizeof(long);    /* default to 'long' results */

    DEBUGMSGTL(("host/hr_network", "... get net stats "));
    DEBUGMSGOID(("host/hr_network", name, *length));
    DEBUGMSG(("host/hr_network", "\n"));
    return LowIndex;
}


        /*********************
	 *
	 *  System specific implementation functions
	 *
	 *********************/


u_char         *
var_hrnet(struct variable * vp,
          oid * name,
          size_t * length,
          int exact, size_t * var_len, WriteMethod ** write_method)
{
    int             net_idx;

    net_idx = header_hrnet(vp, name, length, exact, var_len, write_method);
    if (net_idx == MATCH_FAILED)
        return NULL;


    switch (vp->magic) {
    case HRNET_IFINDEX:
        long_return = net_idx & ((1 << HRDEV_TYPE_SHIFT) - 1);
        return (u_char *) & long_return;
    default:
        DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_hrnet\n",
                    vp->magic));
    }
    return NULL;
}


        /*********************
	 *
	 *  Internal implementation functions
	 *
	 *********************/


#if defined( USING_IF_MIB_IFTABLE_IFTABLE_DATA_ACCESS_MODULE )
static char     HRN_name[16];
static netsnmp_interface_entry *HRN_ifnet;
#define M_Interface_Scan_Next(a, b, c, d)	Interface_Scan_NextInt(a, b, c, d)
#elif defined(hpux11)
static char     HRN_name[MAX_PHYSADDR_LEN];
static nmapi_phystat HRN_ifnet;
#define M_Interface_Scan_Next(a, b, c, d)	Interface_Scan_NextInt(a, b, c)
#elif defined darwin
static char     HRN_name[IFNAMSIZ];
static struct if_msghdr HRN_ifnet;
#define M_Interface_Scan_Next(a, b, c, d)	Interface_Scan_NextInt(a, b, c, d)
#else                           /* hpux11 */
static char     HRN_name[16];
#ifndef WIN32
static struct ifnet HRN_ifnet;
#endif /* WIN32 */
#define M_Interface_Scan_Next(a, b, c, d)	Interface_Scan_NextInt(a, b, c, d)
#endif

#ifdef hpux11
static char     HRN_savedName[MAX_PHYSADDR_LEN];
#else
static char     HRN_savedName[16];
#endif
static u_short  HRN_savedFlags;
static int      HRN_savedErrors;


void
Init_HR_Network(void)
{
#if !defined( solaris2 )
    Interface_Scan_Init();
#endif
}

int
Get_Next_HR_Network(void)
{
int      HRN_index;
#if !(defined(solaris2) || defined(darwin) || defined(WIN32))
    if (M_Interface_Scan_Next(&HRN_index, HRN_name, &HRN_ifnet, NULL) == 0)
        HRN_index = -1;
#else
    HRN_index = -1;
#endif
    if (-1 == HRN_index)
        return HRN_index;

    /*
     * If the index is greater than the shift registry space,
     * this will overrun into the next device type block,
     * potentially resulting in duplicate index values
     * which may cause the agent to crash.
     *   To avoid this, we silently drop interfaces greater
     * than the shift registry size can handle.
     */
    if (HRN_index > (1 << HRDEV_TYPE_SHIFT ))
        return -1;

    return (HRDEV_NETWORK << HRDEV_TYPE_SHIFT) + HRN_index;
}

void
Save_HR_Network_Info(void)
{
    strcpy(HRN_savedName, HRN_name);
#if defined( USING_IF_MIB_IFTABLE_IFTABLE_DATA_ACCESS_MODULE )
    HRN_savedFlags  = HRN_ifnet->os_flags;
    HRN_savedErrors = HRN_ifnet->stats.ierrors + HRN_ifnet->stats.oerrors;
#elif defined( hpux11 )
    HRN_savedFlags  = HRN_ifnet.if_entry.ifOper;
    HRN_savedErrors = HRN_ifnet.if_entry.ifInErrors +
                      HRN_ifnet.if_entry.ifOutErrors;
#elif defined(__APPLE__)       /* or darwin? */
    HRN_savedFlags  = HRN_ifnet.ifm_flags;
    HRN_savedErrors = HRN_ifnet.ifm_data.ifi_ierrors +
                      HRN_ifnet.ifm_data.ifi_oerrors;
#elif !defined(WIN32)
    HRN_savedFlags = HRN_ifnet.if_flags;
    HRN_savedErrors = HRN_ifnet.if_ierrors + HRN_ifnet.if_oerrors;
#endif
}


const char     *
describe_networkIF(int idx)
{
    static char     string[1024];

    snprintf(string, sizeof(string)-1, "network interface %s", HRN_savedName);
    string[ sizeof(string)-1 ] = 0;
    return string;
}


int
network_status(int idx)
{
#ifndef WIN32
#ifdef hpux11
    if (HRN_savedFlags == LINK_UP)
#else
    if (HRN_savedFlags & IFF_UP)
#endif
        return 2;               /* running */
    else
        return 5;               /* down */
#endif /* WIN32 */

}

int
network_errors(int idx)
{
    return HRN_savedErrors;
}
