/*
 *  Copyright (c) 1996-2007 Digi International Inc., All Rights Reserved
 *
 *  This software contains proprietary and confidential information of Digi
 *  International Inc.  By accepting transfer of this copy, Recipient agrees
 *  to retain this software in confidence, to prevent disclosure to others,
 *  and to make no use of this software other than that for which it was
 *  delivered.  This is an unpublished copyrighted work of Digi International
 *  Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 *  prohibited.
 *
 *  Restricted Rights Legend
 *
 *  Use, duplication, or disclosure by the Government is subject to
 *  restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 *  Technical Data and Computer Software clause at DFARS 252.227-7031 or
 *  subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 *  Restricted Rights at 48 CFR 52.227-19, as applicable.
 *
 *  Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 *
*  File Description:
*                    Definitions for SNMP (RFC 1067) implementation.
**************************************************************************/
/***********************************************************
    Copyright 1988, 1989 by Carnegie Mellon University

                      All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of CMU not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/
/*
 * Edit History
 * Date        Initials               Change Description
 *
 * 08/05/03    JZW                    Add manifest constants for trap
 *                                    types and error. Add linked list
 *                                    data structure
 */
#ifndef _SNMPIMPL_
#define _SNMPIMPL_
#ifdef __cplusplus
extern "C"
{
#endif
#include <snmpapi.h>
    
#define COMMUNITY_MAX_LEN   64
#define MAX_NAME_LEN        128  /* number of subid's in a objid */

#ifndef NULL
#define NULL 0
#endif /* NULL */

#ifndef TRUE
#define TRUE    1
#endif /* TRUE */

#ifndef FALSE
#define FALSE   0
#endif /* FALSE */

#define SNMP_MIN(a,b)   ((a)<(b)?(a):(b))
#define SNMP_MAX(a,b)   ((a)>(b)?(a):(b))
#define SNMP_NENT(A)    (sizeof(A)/sizeof(A[0]))

#ifdef SNMP_DEBUG
#define STATIC
#else
#define STATIC static
#endif

/* convert an IP address stored in a long in network order to an OID
    set of four longs   */
#define IP_NET_TO_OID(D,S) \
    ((*(oid*)(D)) = *((u_char*)(S)), \
    (*((oid*)(D)+1)) = *(u_char*)((u_char*)(S)+1), \
    (*((oid*)(D)+2)) = *(u_char*)((u_char*)(S)+2), \
    (*((oid*)(D)+3)) = *(u_char*)((u_char*)(S)+3))
/* convert an OID set of four longs to an IP address stored in a long in
    network order */
#define OID_TO_IP_NET(D,S) \
    ((*((u_char*)D)) = (u_char)(*(oid*)(S)), \
    (*(((u_char*)D)+1)) = (u_char)(*(oid*)((S)+1)), \
    (*(((u_char*)D)+2)) = (u_char)(*(oid*)((S)+2)), \
    (*(((u_char*)D)+3)) = (u_char)(*(oid*)((S)+3)))

#ifdef CPU_IS_BIG_ENDIAN

#define IP_HOST_TO_OID(D,S)     IP_NET_TO_OID(D,S)
#define OID_TO_IP_HOST(D,S)     OID_TO_IP_NET(D,S)

#ifndef ntohs
#define ntohs(val) (u_short)(val)
#endif

#ifndef ntohl
#define ntohl(val) (u_long)(val)
#endif

#else /* CPU_IS_LITTLE_ENDIAN */

/* convert an IP address stored in a long in network order to an OID
    set of four longs   */
#define OID_TO_IP_HOST(D,S) \
    ((*((u_char*)D)) = (u_char)(*(oid*)((S)+3)), \
    (*(((u_char*)D)+1)) = (u_char)(*(oid*)((S)+2)), \
    (*(((u_char*)D)+2)) = (u_char)(*(oid*)((S)+1)), \
    (*(((u_char*)D)+3)) = (u_char)(*(oid*)(S)))

/* convert an IP address stored in a long in host order to an OID
    set of four longs   */
#define IP_HOST_TO_OID(D,S) \
    ((*(oid*)(D)) = *(u_char*)((u_char*)(S)+3), \
    (*((oid*)(D)+1)) = *(u_char*)((u_char*)(S)+2), \
    (*((oid*)(D)+2)) = *(u_char*)((u_char*)(S)+1), \
    (*((oid*)(D)+3)) = *((u_char*)(S)))

#ifndef ntohs
#define ntohs(val) \
    ( (((u_short)(val) >> 8) & 0x00FF) | \
      (((u_short)(val) << 8) & 0xFF00) )
#endif

#ifndef ntohl
#define ntohl(val) \
    ( (((u_long)(val) >> 24) & 0x000000FF) | \
      (((u_long)(val) >> 8)  & 0x0000FF00) | \
      (((u_long)(val) << 8)  & 0x00FF0000) | \
      (((u_long)(val) << 24) & 0xFF000000) )
#endif

#endif  /* CPU_IS_BIG_ENDIAN */

#ifndef htons
#define htons(val) ntohs(val)
#endif

#ifndef htonl
#define htonl(val) ntohl(val)
#endif

/* new manifest constants for trap types, trap errors
 * and trap linked list
 */

typedef struct trap_ipaddress
{
    unsigned int traptypes;
//    NaSnmpTrapAddrInfo_t addrInfo;
    struct trap_ipaddress *prev;
    struct trap_ipaddress *next;
}TRAP_IPADDR;


    
/************************************************************************/
/* message parsing structure                                            */
/************************************************************************/
struct parsePtrs
{
    u_char * bufStart;
    u_char * bufEnd;
    u_char * msgStart;
    u_char * msgEnd;
};

struct varBind;
struct variable;

    
#ifdef TL05
/*
 *  TL05 is a special purpose, non-RFC-compliant API
 *
 *  callerip ---- the SNMP management station (client) IP address
 *  callercommunity --- the SNMP management station (client) community
 *
 */
typedef int(* setMethod)(int action, struct varBind * var, unsigned int callerip, char *callercommunity);
#else
/*ad*
 * callback function setMethod
 *
 * @external
 * @category SNMP
 * @since 6.0
 *
 * @param action	One of these actions:
 *			<list type = "unordered">
 *			   <item> SNMP_SET_RESERVE </item>
 *			   <item> SNMP_SET_ACTION  </item>
 *			   <item> SNMP_SET_FREE    </item>
 *			   <item> SNMP_SET_UNDO    </item>
 *			</list>
 * @param var		pointer to the variable binding
 *
 * @return SNMP_ERR_NOERROR           The write succeeded. 
 * @return SNMP_ERR_TOOBIG            Value is too big.
 * @return SNMP_ERR_NOSUCHNAME        Unable to find object.
 * @return SNMP_ERR_BADVALUE          Value is out of range.
 * @return SNMP_ERR_READONLY          Object is read only.
 * @return SNMP_ERR_GENERR            General error.
 * @return SNMP_ERR_NOACCESS          Access denied.
 * @return SNMP_ERR_WRONGTYPE         The object is a different type than the value passed.
 * @return SNMP_ERR_WRONGLENGTH       The value is the wrong length.
 * @return SNMP_ERR_WRONGENCODING     The value uses the wrong encoding.
 * @return SNMP_ERR_WRONGVALUE        The value is incorrect.
 * @return SNMP_ERR_NOCREATION        Unable to create object.
 * @return SNMP_ERR_INCONSISTENTVALUE Value is inconsistent.
 * @return SNMP_ERR_RESOURCEUNAVAILABLE     Out of memory or some other resource.
 * @return SNMP_ERR_COMMITFAILED      Unable to write to variable.
 * @return SNMP_ERR_UNDOFAILED        Write failed, but was unable to completely restore all fields in the row.
 * @return SNMP_ERR_AUTHORIZATIONERROR Access denied.
 * @return SNMP_ERR_NOTWRITABLE       Object is not writable.
 * @return SNMP_ERR_INCONSISTENTNAME  OID is inconsistent.
 *
 * @see @link varBind
 * @see @link SNMP_ACTIONS
*ad*/
typedef int(* setMethod)(int action, struct varBind * var);
#endif  

#define null_method (setMethod)(0)
#define nullSet (setMethod)(0)

    
#ifdef TL05
/*
 *  TL05 is a special purpose, non-RFC-compliant API
 *
 *  callerip ---- the SNMP management station (client) IP address
 *  callercommunity --- the SNMP management station (client) community
 *
 */
typedef void * (* snmpVarAccess)(struct variable * vp, oid * name, int * length, int exact, int * var_len, setMethod * write_method, unsigned int callerip, char *callercommunity);
#else
/*ad*
 * callback function that finds instance of MIB data
 *
 * @external
 * @category SNMP
 * @since 6.0
 * 
 * @param vp		pointer to the MIB table definition for the variable being accessed.
 * @param name 		the OID of the variable to access (or that preceeds the variable to access)
 * @param length	pointer to the length of the OID. In and out.
 * @param exact		if set OID must match exactly, if not get the next OID
 * @param var_len	pointer to the length of the variable
 * @param write_method	pointer to the address of the routine to call to set this variable
 *
 * @return "pointer to MIB data"  Returns a pointer to an instance of MIB data.
*ad*/
typedef void * (* snmpVarAccess)(struct variable * vp, oid * name, int * length, int exact, int * var_len, setMethod * write_method);
#endif

/*ad*
 * union types for value
 *
 * @external
 * @category SNMP
 * @since 6.0
 *
 * @param intVal        Stores value if object is an intVal.
 * @param integer       Stores value if object is an integer.
 * @param string        Stores value if object is a string.
 * @param objid         Stores value if object is an object ID.
 * @param p64           Stores value if object is a 64-bit value.
 *
 * @see @link u_long
 * @see @link u_char
 * @see @link counter64
 * @see @link oid
*ad*/
union value
{              
    u_long    	intVal;
    u_long *	integer;
    u_char *	string;
    oid *		objid;
    struct counter64 * p64;
};

/*ad*
 * Defines for varBind state
 *
 * @external
 * @category SNMP
 * @since 6.0
 * @name varBind_states "Constants for SNMP varBind state"
 *
 * @param VAR_SET_ALLOCATED   setTo points to allocated data    
 * @param VAR_SET_ASN         setTo points to unparsed asn data  
 * @param VAR_SET_VAL         setTo contains an int (NOT int*)   
 * @param VAR_OID_ALLOCATED   oid points to allocated data       
 * @param VAR_VAL_ALLOCATED   val points to allocated data       
 * @param VAR_VAL_ASN         val points to unparsed asn data    
 * @param VAR_VAL_VAL         val contains an int (NOT int*)     
 * @param VAR_VAL_NULL        val NOT found (set adding row)     
*ad*/
#define VAR_SET_ALLOCATED   0x01    /* setTo points to allocated data   */
#define VAR_SET_ASN         0x02    /* setTo points to unparsed asn data*/
#define VAR_SET_VAL         0x04    /* setTo contains an int (NOT int*) */
#define VAR_OID_ALLOCATED   0x08    /* oid points to allocated data     */
#define VAR_VAL_ALLOCATED   0x10    /* val points to allocated data     */
#define VAR_VAL_ASN         0x20    /* val points to unparsed asn data  */
#define VAR_VAL_VAL         0x40    /* val contains an int (NOT int*)   */
#define VAR_VAL_NULL        0x80    /* val NOT found (set adding row)   */

/*ad*
 * varBind structure
 *
 * @external
 * @category SNMP
 * @since 6.0
 *
 * @param next 		Pointer to the next varBind linked-list, NULL for last variable
 * @param oid		Object identifier of variable
 * @param oidLen	number of subid's in name
 * @param setTo		parsed value from the in stream
 * @param setToLen	length of setTo
 * @param state		varBind state
 * @param type		ASN type of variable
 * @param val		pointer to variable (from getStatPtr)
 * @param valLen	length of val
 * @param vp		pointer to the MIB entry
 * @param set 		pointer to the set method
 *
 * @see @link u_char
 * @see @link value
 * @see @link variable
 * @see @link setMethod
 * @see @link varBind_states
 * @see @link oid
*ad*/
struct varBind
{
    struct varBind *next; 
    oid *oid;           
    int oidLen;         
    union value setTo;  
    int setToLen;       
    u_char state;       
    u_char type;        
    union value val;    
    int valLen;         
    struct variable *vp;
    setMethod set;      
};

/* The data of the message - request type and start of linked list of   */
/* oid variable bindings                                                */
struct ScopedPduData
{
#ifdef SNMP_AGENT_V3
    u_char *contextEngineId;
    int contextEngineIdLen;
    u_char *contextName;
    int contextNameLen;
#endif /* SNMP_AGENT_V3 */
    u_char pduType;     /* Request type of this PDU                     */
    u_long requestId;   /* number to correlate requests with responses  */
    u_long errStatus;   /* Error status                                 */
    u_long errIndex;    /* Error index                                  */
    struct varBind *opList;  /* linked list of variable bindings        */
};

#ifdef SNMP_AGENT_V3
/* V3 security parameters                                               */
struct v3SecurityData
{
    u_char *msgAuthEngineId;    /* the engine Id                        */
    int msgAuthEngineIdLen;
    u_long msgAuthEngineBoots;  /* number of times the system rebooted  */
    u_long msgAuthEngineTime;   /* number of seconds since last reboot  */
    char *msgUserName;          /* user table entry lookup name         */
    int msgUserNameLen;

    int msgAuthParamLen;
    u_char *msgAuthParam;       /* authentication code                  */
    u_char msgAuthCode[32];
    u_char hashAuthKey[20];     /* copy of uuentry.hashedAuthKey        */

    int msgPrivParamLen;
    u_char *msgPrivParam;       /* privacy code                         */
    u_char msgPrivCode[32];
    u_char hashPrivKey[20];     /* copy of uuentry.hashedPrivKey        */

    /* after parsing the message, find the user access information      */
    struct usmUserTable * uuEntry;
    struct vacmAccessTable * vaEntry;
};
#endif /* SNMP_AGENT_V3 */

/* The message header                                                   */
struct HeaderData
{
    char *community;        /* community for outgoing requests.         */
    int communityLen;       /* Length of community name.                */

#ifdef SNMP_AGENT_V3
    long msgId;             /* Request id                               */
    long msgMaxSize;        /* maximum size of a return message         */
    int msgFlags;           /* authentication, privacy and report flags */
    int msgSecurityLevel;   /* 1=noAuthNoPriv, 2=authNoPriv, 3=authPriv */
    long msgSecurityModel;  /* security model (default=3 for V3)        */
#endif /* SNMP_AGENT_V3 */
};

struct parseState
{
    u_char* startOfMsg;
    int lengthOfMsg;
    u_char* endOfMsg;
    u_char* currentPtr;
    int lengthToGo;
};

/* Put it all together. This is what a received message will look like  */
struct snmpMsg
{
    struct parseState ps;
    u_long msgVersion;     /* 0=SNMPv1, 1=SNMPv2c, 2=SNMPv2, 3=SNMPv3   */
    struct HeaderData msgGlobalData;
#ifdef SNMP_AGENT_V3
    struct v3SecurityData msgSecurity;
#endif /* SNMP_AGENT_V3 */
    struct ScopedPduData msgData;
};

struct oidList
{
    oid * oid;
    int oidLen;
};

#define SNMP_GET    1
#define SNMP_SET    0

/*ad*
 * Defines for set actions
 *
 * @external
 * @category SNMP
 * @since 6.0
 * @name SNMP_ACTIONS "Constants for SNMP set actions"
 *
 * @param SNMP_SET_RESERVE     1
 * @param SNMP_SET_COMMIT      2
 * @param SNMP_SET_ACTION      3
 * @param SNMP_SET_FREE        4
 * @param SNMP_SET_UNDO        5
*ad*/
#define SNMP_SET_RESERVE     1
#define SNMP_SET_COMMIT      2
#define SNMP_SET_ACTION      3
#define SNMP_SET_FREE        4
#define SNMP_SET_UNDO        5

#ifdef ML_DEBUG
#define RONLY       0xAAAA  /* read access for everyone                 */
#define RWRITE      0xAABB  /* add write access for community private   */
#define RCREATE     0xAABB  /* add write access for community private   */
#define NOACCESS    0x0000  /* no access for anybody                    */
#endif /* ML_DEBUG */

/* Defines for Access Control Level (acl) in variable structure         */
#define RONLY       0x01
#define RWRITE      0x03
#define RCREATE     0x07
#define ANOTIFY     0x08
#define NOACCESS    0x00

#define ACL_READ    0x01
#define ACL_WRITE   0x02
#define ACL_CREATE  0x04
#define ACL_NOTIFY  0x08

/* data type defines */
#define INTEGER     ASN_INTEGER
#define STRING      ASN_OCTET_STR
#define OBJID       ASN_OBJECT_ID
#define NULLOBJ     ASN_NULL
#define BITSTRING   ASN_BIT_STR
        /* defined types (from the SMI, RFC 1157) */
#define IPADDRESS   (ASN_APPLICATION | 0)
#define COUNTER     (ASN_APPLICATION | 1)
#define GAUGE       (ASN_APPLICATION | 2)
#define TIMETICKS   (ASN_APPLICATION | 3)
#define OPAQUE      (ASN_APPLICATION | 4)
        /* defined types (from the SMI) */
#define NSAP        (ASN_APPLICATION | 5)
#define COUNTER64   (ASN_APPLICATION | 6)
#define UINTEGER    (ASN_APPLICATION | 7)

/* RFC2571 SnmpSecurityModel Textual Convention defines security model  */
typedef int tSecModel;
#define SEC_ANY             0
#define SEC_SNMP_V1         1
#define SEC_SNMP_V2         2
#define SEC_USM             3

/* RFC2571 SnmpSecurityLevel Textual Convention defines security level  */
typedef int tSecLevel;
#define SEC_NO_AUTH_NO_PRIV     1
#define SEC_AUTH_NO_PRIV        2
#define SEC_AUTH_PRIV           3

/* RFC2579 defines row status */
typedef int tStatus;
#define STATUS_ACTIVE           1
#define STATUS_NOT_IN_SERVICE   2
#define STATUS_NOT_READY        3
#define STATUS_CREATE_AND_GO    4
#define STATUS_CREATE_AND_WAIT  5
#define STATUS_DESTROY          6

/* RFC2579 defines row storage type */
typedef int tStorage;
#define STORAGE_OTHER       1
#define STORAGE_VOLATILE    2
#define STORAGE_NONVOLATILE 3
#define STORAGE_PERMANENT   4
#define STORAGE_READ_ONLY   5


/* Prototypes for routines in os_deps.c */
u_long NASnmpGetSysUpTime(void);

#ifdef SNMP_AGENT_V3
    u_long NASnmpGetEngineTime(void);
    
    /* Prototypes for snmpage.c routines                                    */
    int snmpMsgIsPrivate(void);
    u_char * snmpMsgGetUser(int * pOutLen);
#endif /* SNMP_AGENT_V3 */

#define MAX_NUM_COMMUNITIES 2
#define COMMUNITY_LENGTH    24
#define SNMP_READ_COMMUNITY_INDEX   0
#define SNMP_WRITE_COMMUNITY_INDEX  1

#ifdef SNMP_DEBUG

        /* Each time a function is entered, track the name of the function  */
        /* Then when the routine is exited, set the current function to the */
        /* function the calling function                                    */
extern char* _snmp_current_func;
#define ENTER(X)    char* _called_by = _snmp_current_func; \
    _snmp_current_func = X; SNMP_DEBUG1("Enter %s\n", X)
#define __BYE       SNMP_DEBUG1("Exit %s\n", _snmp_current_func); \
    _snmp_current_func = _called_by
#define LEAVE()     __BYE; return
#define RETURN(X)   __BYE; return(X)

#else /* not SNMP_DEBUG */

#define ENTER(X)
#define LEAVE()
#define RETURN(X)   return(X)

#endif /* SNMP_DEBUG */
#ifdef __cplusplus
}
#endif

#endif /* _SNMPIMPL_ */



